Add ability to output ImageBaseGSUrl to render_picture and use in rebaseline server.

BUG=skia:2230
R=epoger@google.com

Author: rmistry@google.com

Review URL: https://codereview.chromium.org/479613002
This commit is contained in:
rmistry 2014-08-22 04:46:30 -07:00 committed by Commit bot
parent 85b438dfab
commit 2529f2e72c
14 changed files with 416 additions and 46 deletions

View File

@ -94,6 +94,7 @@ JSONKEY_IMAGE_COMPARISONRESULT = 'comparisonResult'
JSONKEY_IMAGE_FILEPATH = 'filepath'
JSONKEY_SOURCE_TILEDIMAGES = 'tiled-images'
JSONKEY_SOURCE_WHOLEIMAGE = 'whole-image'
JSONKEY_IMAGE_BASE_GS_URL = 'image-base-gs-url'
# Root directory where the buildbots store their actually-generated images...

View File

@ -151,7 +151,8 @@ class ConfigComparisons(results.BaseComparisons):
try:
image_pair = imagepair.ImagePair(
image_diff_db=self._image_diff_db,
base_url=gm_json.GM_ACTUALS_ROOT_HTTP_URL,
imageA_base_url=gm_json.GM_ACTUALS_ROOT_HTTP_URL,
imageB_base_url=gm_json.GM_ACTUALS_ROOT_HTTP_URL,
imageA_relative_url=configA_image_relative_url,
imageB_relative_url=configB_image_relative_url,
extra_columns=extra_columns_dict)

View File

@ -268,18 +268,25 @@ class RenderedPicturesComparisons(results.BaseComparisons):
self._validate_dict_version(dictB)
dictB_results = self.get_default(dictB, {}, setB_section)
image_A_base_url = self.get_default(
setA_dicts, self._image_base_gs_url, dict_path,
gm_json.JSONKEY_IMAGE_BASE_GS_URL)
image_B_base_url = self.get_default(
setB_dicts, self._image_base_gs_url, dict_path,
gm_json.JSONKEY_IMAGE_BASE_GS_URL)
# get the builders and render modes for each set
builder_A = self.get_default(dictA, None,
gm_json.JSONKEY_DESCRIPTIONS,
builder_A = self.get_default(dictA, None,
gm_json.JSONKEY_DESCRIPTIONS,
gm_json.JSONKEY_DESCRIPTIONS_BUILDER)
render_mode_A = self.get_default(dictA, None,
gm_json.JSONKEY_DESCRIPTIONS,
render_mode_A = self.get_default(dictA, None,
gm_json.JSONKEY_DESCRIPTIONS,
gm_json.JSONKEY_DESCRIPTIONS_RENDER_MODE)
builder_B = self.get_default(dictB, None,
gm_json.JSONKEY_DESCRIPTIONS,
builder_B = self.get_default(dictB, None,
gm_json.JSONKEY_DESCRIPTIONS,
gm_json.JSONKEY_DESCRIPTIONS_BUILDER)
render_mode_B = self.get_default(dictB, None,
gm_json.JSONKEY_DESCRIPTIONS,
render_mode_B = self.get_default(dictB, None,
gm_json.JSONKEY_DESCRIPTIONS,
gm_json.JSONKEY_DESCRIPTIONS_RENDER_MODE)
skp_names = sorted(set(dictA_results.keys() + dictB_results.keys()))
@ -295,8 +302,11 @@ class RenderedPicturesComparisons(results.BaseComparisons):
whole_image_B = self.get_default(
dictB_results, None,
skp_name, gm_json.JSONKEY_SOURCE_WHOLEIMAGE)
imagepairs_for_this_skp.append(self._create_image_pair(
image_dict_A=whole_image_A, image_dict_B=whole_image_B,
image_A_base_url=image_A_base_url,
image_B_base_url=image_B_base_url,
builder_A=builder_A, render_mode_A=render_mode_A,
builder_B=builder_B, render_mode_B=render_mode_B,
source_json_file=dict_path,
@ -318,6 +328,8 @@ class RenderedPicturesComparisons(results.BaseComparisons):
if tile_num < num_tiles_A else None),
image_dict_B=(tiled_images_B[tile_num]
if tile_num < num_tiles_B else None),
image_A_base_url=image_A_base_url,
image_B_base_url=image_B_base_url,
builder_A=builder_A, render_mode_A=render_mode_A,
builder_B=builder_B, render_mode_B=render_mode_B,
source_json_file=dict_path,
@ -368,8 +380,9 @@ class RenderedPicturesComparisons(results.BaseComparisons):
raise Exception('expected header_revision %d, but got %d' % (
expected_header_revision, header_revision))
def _create_image_pair(self, image_dict_A, image_dict_B,
builder_A, render_mode_A,
def _create_image_pair(self, image_dict_A, image_dict_B,
image_A_base_url, image_B_base_url,
builder_A, render_mode_A,
builder_B, render_mode_B,
source_json_file,
source_skp_name, tilenum):
@ -378,11 +391,13 @@ class RenderedPicturesComparisons(results.BaseComparisons):
Args:
image_dict_A: dict with JSONKEY_IMAGE_* keys, or None if no image
image_dict_B: dict with JSONKEY_IMAGE_* keys, or None if no image
image_A_base_url: base URL for image A
image_B_base_url: base URL for image B
builder_A: builder that created image set A or None if unknow
render_mode_A: render mode used to generate image set A or None if
render_mode_A: render mode used to generate image set A or None if
unknown.
builder_B: builder that created image set A or None if unknow
render_mode_B: render mode used to generate image set A or None if
render_mode_B: render mode used to generate image set A or None if
unknown.
source_json_file: string; relative path of the JSON file where this
result came from, within setA and setB.
@ -436,7 +451,8 @@ class RenderedPicturesComparisons(results.BaseComparisons):
try:
return imagepair.ImagePair(
image_diff_db=self._image_diff_db,
base_url=self._image_base_gs_url,
imageA_base_url=image_A_base_url,
imageB_base_url=image_B_base_url,
imageA_relative_url=imageA_relative_url,
imageB_relative_url=imageB_relative_url,
extra_columns=extra_columns_dict,

View File

@ -32,6 +32,7 @@ import compare_rendered_pictures
import find_run_binary
import gm_json
import imagediffdb
import imagepairset
import results
@ -78,6 +79,64 @@ class CompareRenderedPicturesTest(base_unittest.TestCase):
results.KEY__HEADER__RESULTS_ALL),
os.path.join(self.output_dir_actual, 'compare_rendered_pictures.json'))
def test_endToEnd_withImageBaseGSUrl(self):
"""Generate two sets of SKPs, run render_pictures over both, and compare
the results."""
setA_subdir = 'before_patch'
setB_subdir = 'after_patch'
imageA_gs_base = 'superman/kent-camera/pictures'
imageB_gs_base = 'batman/batarang/pictures'
self._generate_skps_and_run_render_pictures(
subdir=setA_subdir, skpdict={
'changed.skp': 200,
'unchanged.skp': 100,
'only-in-before.skp': 128,
},
image_base_gs_url='gs://%s' % imageA_gs_base)
self._generate_skps_and_run_render_pictures(
subdir=setB_subdir, skpdict={
'changed.skp': 201,
'unchanged.skp': 100,
'only-in-after.skp': 128,
},
image_base_gs_url='gs://%s' % imageB_gs_base)
results_obj = compare_rendered_pictures.RenderedPicturesComparisons(
setA_dir=os.path.join(self.temp_dir, setA_subdir),
setB_dir=os.path.join(self.temp_dir, setB_subdir),
setA_section=gm_json.JSONKEY_ACTUALRESULTS,
setB_section=gm_json.JSONKEY_ACTUALRESULTS,
image_diff_db=imagediffdb.ImageDiffDB(self.temp_dir),
image_base_gs_url='gs://fakebucket/fake/path',
diff_base_url='/static/generated-images')
results_obj.get_timestamp = mock_get_timestamp
output_dict = results_obj.get_packaged_results_of_type(
results.KEY__HEADER__RESULTS_ALL)
# Assert that the baseURLs are as expected.
self.assertEquals(
output_dict[imagepairset.KEY__ROOT__IMAGESETS]
[imagepairset.KEY__IMAGESETS__SET__IMAGE_A]
[imagepairset.KEY__IMAGESETS__FIELD__BASE_URL],
'http://storage.cloud.google.com/%s' % imageA_gs_base)
self.assertEquals(
output_dict[imagepairset.KEY__ROOT__IMAGESETS]
[imagepairset.KEY__IMAGESETS__SET__IMAGE_B]
[imagepairset.KEY__IMAGESETS__FIELD__BASE_URL],
'http://storage.cloud.google.com/%s' % imageB_gs_base)
# Overwrite elements within the results that change from one test run
# to the next.
# pylint: disable=W0212
results_obj._setA_descriptions[results.KEY__SET_DESCRIPTIONS__DIR] = [
'before-patch-fake-dir']
results_obj._setB_descriptions[results.KEY__SET_DESCRIPTIONS__DIR] = [
'after-patch-fake-dir']
gm_json.WriteToFile(
output_dict,
os.path.join(self.output_dir_actual,
'compare_rendered_pictures.json'))
def test_repo_url(self):
"""Use repo: URL to specify summary files."""
base_repo_url = 'repo:gm/rebaseline_server/testdata/inputs/skp-summaries'
@ -104,7 +163,8 @@ class CompareRenderedPicturesTest(base_unittest.TestCase):
results.KEY__HEADER__RESULTS_ALL),
os.path.join(self.output_dir_actual, 'compare_rendered_pictures.json'))
def _generate_skps_and_run_render_pictures(self, subdir, skpdict):
def _generate_skps_and_run_render_pictures(self, subdir, skpdict,
image_base_gs_url=None):
"""Generate SKPs and run render_pictures on them.
Args:
@ -121,13 +181,16 @@ class CompareRenderedPicturesTest(base_unittest.TestCase):
# and fix its result! (imageURLs within whole-image entries are wrong when
# I tried adding that)
binary = find_run_binary.find_path_to_program('render_pictures')
return subprocess.check_output([
render_pictures_cmd = [
binary,
'--config', '8888',
'-r', out_path,
'--writeChecksumBasedFilenames',
'--writeJsonSummaryPath', os.path.join(out_path, 'summary.json'),
'--writePath', out_path])
'--writePath', out_path]
if image_base_gs_url:
render_pictures_cmd.extend(['--imageBaseGSUrl', image_base_gs_url])
return subprocess.check_output(render_pictures_cmd)
def _run_skpmaker(self, output_path, red=0, green=0, blue=0,
width=640, height=400):

View File

@ -347,7 +347,8 @@ class ExpectationComparisons(results.BaseComparisons):
try:
image_pair = imagepair.ImagePair(
image_diff_db=self._image_diff_db,
base_url=gm_json.GM_ACTUALS_ROOT_HTTP_URL,
imageA_base_url=gm_json.GM_ACTUALS_ROOT_HTTP_URL,
imageB_base_url=gm_json.GM_ACTUALS_ROOT_HTTP_URL,
imageA_relative_url=expected_image_relative_url,
imageB_relative_url=actual_image_relative_url,
expectations=expectations_dict,

View File

@ -32,17 +32,19 @@ class ImagePair(object):
"""
def __init__(self, image_diff_db,
base_url, imageA_relative_url, imageB_relative_url,
imageA_base_url, imageB_base_url,
imageA_relative_url, imageB_relative_url,
expectations=None, extra_columns=None, source_json_file=None,
download_all_images=False):
"""
Args:
image_diff_db: ImageDiffDB instance we use to generate/store image diffs
base_url: base of all image URLs
imageA_base_url: string; base URL for image A
imageB_base_url: string; base URL for image B
imageA_relative_url: string; URL pointing at an image, relative to
base_url; or None, if this image is missing
imageA_base_url; or None, if this image is missing
imageB_relative_url: string; URL pointing at an image, relative to
base_url; or None, if this image is missing
imageB_base_url; or None, if this image is missing
expectations: optional dictionary containing expectations-specific
metadata (ignore-failure, bug numbers, etc.)
extra_columns: optional dictionary containing more metadata (test name,
@ -55,7 +57,8 @@ class ImagePair(object):
(imageA == imageB, or one of them is missing)
"""
self._image_diff_db = image_diff_db
self.base_url = base_url
self.imageA_base_url = imageA_base_url
self.imageB_base_url = imageB_base_url
self.imageA_relative_url = imageA_relative_url
self.imageB_relative_url = imageB_relative_url
self.expectations_dict = expectations
@ -76,9 +79,11 @@ class ImagePair(object):
if self._diff_record != None or download_all_images:
image_diff_db.add_image_pair(
expected_image_locator=imageA_relative_url,
expected_image_url=self.posixpath_join(base_url, imageA_relative_url),
expected_image_url=self.posixpath_join(imageA_base_url,
imageA_relative_url),
actual_image_locator=imageB_relative_url,
actual_image_url=self.posixpath_join(base_url, imageB_relative_url))
actual_image_url=self.posixpath_join(imageB_base_url,
imageB_relative_url))
def as_dict(self):
"""Returns a dictionary describing this ImagePair.

View File

@ -91,7 +91,7 @@ class ImagePairTest(unittest.TestCase):
'perceptualDifference': 0.06620300000000157,
'diffUrl': 'arcofzorro_16206093933823793653_png_png-vs-' +
'arcofzorro_13786535001616823825_png_png.png',
'whiteDiffUrl': 'arcofzorro_16206093933823793653_png_png' +
'whiteDiffUrl': 'arcofzorro_16206093933823793653_png_png' +
'-vs-arcofzorro_13786535001616823825_png_png.png',
},
'imageAUrl': 'arcofzorro/16206093933823793653.png',
@ -195,7 +195,8 @@ class ImagePairTest(unittest.TestCase):
for selftest in selftests:
image_pair = imagepair.ImagePair(
image_diff_db=db,
base_url=IMG_URL_BASE,
imageA_base_url=IMG_URL_BASE,
imageB_base_url=IMG_URL_BASE,
imageA_relative_url=selftest[0],
imageB_relative_url=selftest[1],
expectations=selftest[2],

View File

@ -57,7 +57,8 @@ class ImagePairSet(object):
self._descriptions = descriptions or DEFAULT_DESCRIPTIONS
self._extra_column_tallies = {} # maps column_id -> values
# -> instances_per_value
self._image_base_url = None
self._imageA_base_url = None
self._imageB_base_url = None
self._diff_base_url = diff_base_url
# We build self._image_pair_objects incrementally as calls come into
@ -70,11 +71,15 @@ class ImagePairSet(object):
"""Adds an ImagePair; this may be repeated any number of times."""
# Special handling when we add the first ImagePair...
if not self._image_pair_objects:
self._image_base_url = image_pair.base_url
self._imageA_base_url = image_pair.imageA_base_url
self._imageB_base_url = image_pair.imageB_base_url
if image_pair.base_url != self._image_base_url:
if(image_pair.imageA_base_url != self._imageA_base_url):
raise Exception('added ImagePair with base_url "%s" instead of "%s"' % (
image_pair.base_url, self._image_base_url))
image_pair.imageA_base_url, self._imageA_base_url))
if(image_pair.imageB_base_url != self._imageB_base_url):
raise Exception('added ImagePair with base_url "%s" instead of "%s"' % (
image_pair.imageB_base_url, self._imageB_base_url))
self._image_pair_objects.append(image_pair)
extra_columns_dict = image_pair.extra_columns_dict
if extra_columns_dict:
@ -171,10 +176,14 @@ class ImagePairSet(object):
key_description = KEY__IMAGESETS__FIELD__DESCRIPTION
key_base_url = KEY__IMAGESETS__FIELD__BASE_URL
if gs_utils.GSUtils.is_gs_url(self._image_base_url):
value_base_url = self._convert_gs_url_to_http_url(self._image_base_url)
if gs_utils.GSUtils.is_gs_url(self._imageA_base_url):
valueA_base_url = self._convert_gs_url_to_http_url(self._imageA_base_url)
else:
value_base_url = self._image_base_url
valueA_base_url = self._imageA_base_url
if gs_utils.GSUtils.is_gs_url(self._imageB_base_url):
valueB_base_url = self._convert_gs_url_to_http_url(self._imageB_base_url)
else:
valueB_base_url = self._imageB_base_url
# We've waited as long as we can to ask ImageDiffDB for details of the
# image diffs, so that it has time to compute them.
@ -188,11 +197,11 @@ class ImagePairSet(object):
KEY__ROOT__IMAGESETS: {
KEY__IMAGESETS__SET__IMAGE_A: {
key_description: self._descriptions[0],
key_base_url: value_base_url,
key_base_url: valueA_base_url,
},
KEY__IMAGESETS__SET__IMAGE_B: {
key_description: self._descriptions[1],
key_base_url: value_base_url,
key_base_url: valueB_base_url,
},
KEY__IMAGESETS__SET__DIFFS: {
key_description: 'color difference per channel',

View File

@ -79,9 +79,12 @@ class ImagePairSetTest(unittest.TestCase):
"""Assembles some ImagePairs into an ImagePairSet, and validates results.
"""
image_pairs = [
MockImagePair(base_url=BASE_URL_1, dict_to_return=IMAGEPAIR_1_AS_DICT),
MockImagePair(base_url=BASE_URL_1, dict_to_return=IMAGEPAIR_2_AS_DICT),
MockImagePair(base_url=BASE_URL_1, dict_to_return=IMAGEPAIR_3_AS_DICT),
MockImagePair(imageA_base_url=BASE_URL_1, imageB_base_url=BASE_URL_1,
dict_to_return=IMAGEPAIR_1_AS_DICT),
MockImagePair(imageA_base_url=BASE_URL_1, imageB_base_url=BASE_URL_1,
dict_to_return=IMAGEPAIR_2_AS_DICT),
MockImagePair(imageA_base_url=BASE_URL_1, imageB_base_url=BASE_URL_1,
dict_to_return=IMAGEPAIR_3_AS_DICT),
]
expected_imageset_dict = {
'extraColumnHeaders': {
@ -150,12 +153,14 @@ class ImagePairSetTest(unittest.TestCase):
image_pair_set = imagepairset.ImagePairSet(
diff_base_url=DIFF_BASE_URL)
image_pair_set.add_image_pair(
MockImagePair(base_url=BASE_URL_1, dict_to_return=IMAGEPAIR_1_AS_DICT))
MockImagePair(imageA_base_url=BASE_URL_1, imageB_base_url=BASE_URL_1,
dict_to_return=IMAGEPAIR_1_AS_DICT))
image_pair_set.add_image_pair(
MockImagePair(base_url=BASE_URL_1, dict_to_return=IMAGEPAIR_2_AS_DICT))
MockImagePair(imageA_base_url=BASE_URL_1, imageB_base_url=BASE_URL_1,
dict_to_return=IMAGEPAIR_2_AS_DICT))
with self.assertRaises(Exception):
image_pair_set.add_image_pair(
MockImagePair(base_url=BASE_URL_2,
MockImagePair(imageA_base_url=BASE_URL_2, imageB_base_url=BASE_URL_2,
dict_to_return=IMAGEPAIR_3_AS_DICT))
def test_missing_column_ids(self):
@ -164,9 +169,11 @@ class ImagePairSetTest(unittest.TestCase):
image_pair_set = imagepairset.ImagePairSet(
diff_base_url=DIFF_BASE_URL)
image_pair_set.add_image_pair(
MockImagePair(base_url=BASE_URL_1, dict_to_return=IMAGEPAIR_1_AS_DICT))
MockImagePair(imageA_base_url=BASE_URL_1, imageB_base_url=BASE_URL_1,
dict_to_return=IMAGEPAIR_1_AS_DICT))
image_pair_set.add_image_pair(
MockImagePair(base_url=BASE_URL_1, dict_to_return=IMAGEPAIR_2_AS_DICT))
MockImagePair(imageA_base_url=BASE_URL_1, imageB_base_url=BASE_URL_1,
dict_to_return=IMAGEPAIR_2_AS_DICT))
# Call as_dict() with default or reasonable column_ids_in_order.
image_pair_set.as_dict()
image_pair_set.as_dict(column_ids_in_order=['test', 'builder'])
@ -178,13 +185,14 @@ class ImagePairSetTest(unittest.TestCase):
class MockImagePair(object):
"""Mock ImagePair object, which will return canned results."""
def __init__(self, base_url, dict_to_return):
def __init__(self, imageA_base_url, imageB_base_url, dict_to_return):
"""
Args:
base_url: base_url attribute for this object
dict_to_return: dictionary to return from as_dict()
"""
self.base_url = base_url
self.imageA_base_url = imageA_base_url
self.imageB_base_url = imageB_base_url
self.extra_columns_dict = dict_to_return.get(
imagepair.KEY__IMAGEPAIRS__EXTRACOLUMNS, None)
self._dict_to_return = dict_to_return

View File

@ -0,0 +1,237 @@
{
"extraColumnHeaders": {
"builderA": {
"headerText": "builderA",
"isFilterable": true,
"isSortable": true,
"useFreeformFilter": false,
"valuesAndCounts": [
[
null,
4
]
]
},
"builderB": {
"headerText": "builderB",
"isFilterable": true,
"isSortable": true,
"useFreeformFilter": false,
"valuesAndCounts": [
[
null,
4
]
]
},
"renderModeA": {
"headerText": "renderModeA",
"isFilterable": true,
"isSortable": true,
"useFreeformFilter": false,
"valuesAndCounts": [
[
null,
4
]
]
},
"renderModeB": {
"headerText": "renderModeB",
"isFilterable": true,
"isSortable": true,
"useFreeformFilter": false,
"valuesAndCounts": [
[
null,
4
]
]
},
"resultType": {
"headerText": "resultType",
"isFilterable": true,
"isSortable": true,
"useFreeformFilter": false,
"valuesAndCounts": [
[
"failed",
1
],
[
"no-comparison",
2
],
[
"succeeded",
1
]
]
},
"sourceSkpFile": {
"headerText": "sourceSkpFile",
"isFilterable": true,
"isSortable": true,
"useFreeformFilter": true,
"valuesAndCounts": [
[
"changed.skp",
1
],
[
"only-in-after.skp",
1
],
[
"only-in-before.skp",
1
],
[
"unchanged.skp",
1
]
]
},
"tiledOrWhole": {
"headerText": "tiledOrWhole",
"isFilterable": true,
"isSortable": true,
"useFreeformFilter": false,
"valuesAndCounts": [
[
"whole",
4
]
]
},
"tilenum": {
"headerText": "tilenum",
"isFilterable": true,
"isSortable": true,
"useFreeformFilter": true,
"valuesAndCounts": [
[
"N/A",
4
]
]
}
},
"extraColumnOrder": [
"resultType",
"sourceSkpFile",
"tiledOrWhole",
"tilenum",
"builderA",
"renderModeA",
"builderB",
"renderModeB"
],
"header": {
"dataHash": "-5707186260478709107",
"isEditable": false,
"isExported": true,
"schemaVersion": 5,
"setA": {
"dir": [
"before-patch-fake-dir"
],
"repoRevision": null,
"section": "actual-results"
},
"setB": {
"dir": [
"after-patch-fake-dir"
],
"repoRevision": null,
"section": "actual-results"
},
"timeNextUpdateAvailable": null,
"timeUpdated": 12345678,
"type": "all"
},
"imagePairs": [
{
"extraColumns": {
"builderA": null,
"builderB": null,
"renderModeA": null,
"renderModeB": null,
"resultType": "failed",
"sourceSkpFile": "changed.skp",
"tiledOrWhole": "whole",
"tilenum": "N/A"
},
"imageAUrl": "changed_skp/bitmap-64bitMD5_3101044995537104462.png",
"imageBUrl": "changed_skp/bitmap-64bitMD5_13623922271964399662.png",
"isDifferent": true,
"sourceJsonFile": "./summary.json"
},
{
"extraColumns": {
"builderA": null,
"builderB": null,
"renderModeA": null,
"renderModeB": null,
"resultType": "no-comparison",
"sourceSkpFile": "only-in-after.skp",
"tiledOrWhole": "whole",
"tilenum": "N/A"
},
"imageAUrl": null,
"imageBUrl": "only-in-after_skp/bitmap-64bitMD5_2320185040577047131.png",
"isDifferent": true,
"sourceJsonFile": "./summary.json"
},
{
"extraColumns": {
"builderA": null,
"builderB": null,
"renderModeA": null,
"renderModeB": null,
"resultType": "no-comparison",
"sourceSkpFile": "only-in-before.skp",
"tiledOrWhole": "whole",
"tilenum": "N/A"
},
"imageAUrl": "only-in-before_skp/bitmap-64bitMD5_2320185040577047131.png",
"imageBUrl": null,
"isDifferent": true,
"sourceJsonFile": "./summary.json"
},
{
"extraColumns": {
"builderA": null,
"builderB": null,
"renderModeA": null,
"renderModeB": null,
"resultType": "succeeded",
"sourceSkpFile": "unchanged.skp",
"tiledOrWhole": "whole",
"tilenum": "N/A"
},
"imageAUrl": "unchanged_skp/bitmap-64bitMD5_3322248763049618493.png",
"imageBUrl": "unchanged_skp/bitmap-64bitMD5_3322248763049618493.png",
"isDifferent": false,
"sourceJsonFile": "./summary.json"
}
],
"imageSets": {
"diffs": {
"baseUrl": "/static/generated-images/diffs",
"description": "color difference per channel"
},
"imageA": {
"baseUrl": "http://storage.cloud.google.com/superman/kent-camera/pictures",
"description": "setA"
},
"imageB": {
"baseUrl": "http://storage.cloud.google.com/batman/batarang/pictures",
"description": "setB"
},
"whiteDiffs": {
"baseUrl": "/static/generated-images/whitediffs",
"description": "differing pixels in white"
}
}
}

View File

@ -30,6 +30,7 @@
const static char kJsonKey_ActualResults[] = "actual-results";
const static char kJsonKey_Descriptions[] = "descriptions";
const static char kJsonKey_ExpectedResults[] = "expected-results";
const static char kJsonKey_ImageBaseGSUrl[] = "image-base-gs-url";
const static char kJsonKey_Header[] = "header";
const static char kJsonKey_Header_Type[] = "type";
const static char kJsonKey_Header_Revision[] = "revision";
@ -198,6 +199,10 @@ namespace sk_tools {
fDescriptions[key] = value;
}
void ImageResultsAndExpectations::setImageBaseGSUrl(const char *imageBaseGSUrl) {
fImageBaseGSUrl = imageBaseGSUrl;
}
Expectation ImageResultsAndExpectations::getExpectation(const char *sourceName,
const int *tileNumber) {
if (fExpectedResults.isNull()) {
@ -228,6 +233,7 @@ namespace sk_tools {
root[kJsonKey_ActualResults] = fActualResults;
root[kJsonKey_Descriptions] = fDescriptions;
root[kJsonKey_Header] = header;
root[kJsonKey_ImageBaseGSUrl] = fImageBaseGSUrl;
std::string jsonStdString = root.toStyledString();
SkFILEWStream stream(filename);
stream.write(jsonStdString.c_str(), jsonStdString.length());

View File

@ -184,6 +184,13 @@ namespace sk_tools {
*/
void addDescription(const char *key, const char *value);
/**
* Adds the image base Google Storage URL to the summary of results.
*
* @param imageBaseGSUrl the image base Google Storage URL
*/
void setImageBaseGSUrl(const char *imageBaseGSUrl);
/**
* Returns the Expectation for this test.
*
@ -217,6 +224,7 @@ namespace sk_tools {
Json::Value fDescriptions;
Json::Value fExpectedJsonRoot;
Json::Value fExpectedResults;
Json::Value fImageBaseGSUrl;
};
} // namespace sk_tools

View File

@ -30,6 +30,7 @@ DEFINE_bool(bench_record, false, "If true, drop into an infinite loop of recordi
DECLARE_bool(deferImageDecoding);
DEFINE_string(descriptions, "", "one or more key=value pairs to add to the descriptions section "
"of the JSON summary.");
DEFINE_string(imageBaseGSUrl, "", "The Google Storage image base URL the images are stored in.");
DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Components that differ "
"by more than this amount are considered errors, though all diffs are reported. "
"Requires --validate.");
@ -498,6 +499,9 @@ int tool_main(int argc, char** argv) {
SkASSERT(tokens.count() == 2);
jsonSummary.addDescription(tokens[0].c_str(), tokens[1].c_str());
}
if (FLAGS_imageBaseGSUrl.count() == 1) {
jsonSummary.setImageBaseGSUrl(FLAGS_imageBaseGSUrl[0]);
}
jsonSummary.writeToFile(FLAGS_writeJsonSummaryPath[0]);
}
return 0;

View File

@ -197,6 +197,7 @@ class RenderPicturesTest(base_unittest.TestCase):
'--writeWholeImage'])
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {
@ -233,6 +234,7 @@ class RenderPicturesTest(base_unittest.TestCase):
modified_red_tiles[5]['comparisonResult'] = 'failure-ignored'
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {
@ -270,6 +272,7 @@ class RenderPicturesTest(base_unittest.TestCase):
modified_red_tiles[5]['comparisonResult'] = 'no-comparison'
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {
@ -315,6 +318,7 @@ class RenderPicturesTest(base_unittest.TestCase):
if expected_summary_dict == None:
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {
@ -340,6 +344,7 @@ class RenderPicturesTest(base_unittest.TestCase):
pass
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {
@ -370,6 +375,7 @@ class RenderPicturesTest(base_unittest.TestCase):
])
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : {
"builder": "builderName",
"renderMode": "renderModeName",
@ -421,6 +427,7 @@ class RenderPicturesTest(base_unittest.TestCase):
'--writeJsonSummaryPath', output_json_path])
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {
@ -449,6 +456,7 @@ class RenderPicturesTest(base_unittest.TestCase):
'--writeJsonSummaryPath', output_json_path])
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {
@ -484,6 +492,7 @@ class RenderPicturesTest(base_unittest.TestCase):
'--writeJsonSummaryPath', output_json_path])
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {
@ -515,6 +524,7 @@ class RenderPicturesTest(base_unittest.TestCase):
'--writeJsonSummaryPath', output_json_path])
expected_summary_dict = {
"header" : EXPECTED_HEADER_CONTENTS,
"image-base-gs-url" : None,
"descriptions" : None,
"actual-results" : {
"red.skp": {