Index: tools/skpdiff/skpdiff_server.py |
diff --git a/tools/skpdiff/skpdiff_server.py b/tools/skpdiff/skpdiff_server.py |
index 14035403a286d14fd89f692645a78c1d52797d48..053291af9a6caf71297475ab5c50b8e7a1bdcaa1 100755 |
--- a/tools/skpdiff/skpdiff_server.py |
+++ b/tools/skpdiff/skpdiff_server.py |
@@ -99,6 +99,8 @@ def download_gm_image(image_name, image_path, hash_val): |
@param image_path Path to place the image. |
@param hash_val The hash value of the image. |
""" |
+ if hash_val is None: |
+ return |
# Separate the test name from a image name |
image_match = IMAGE_FILENAME_RE.match(image_name) |
@@ -174,14 +176,18 @@ class GMInstance: |
- image_name = the GM test name and config |
- expected_hash = the current expected hash value |
- actual_hash = the actual hash value |
+ - is_rebaselined = True if actual_hash is what is currently in the expected |
+ results file, False otherwise. |
""" |
def __init__(self, |
device_name, image_name, |
- expected_hash, actual_hash): |
+ expected_hash, actual_hash, |
+ is_rebaselined): |
self.device_name = device_name |
self.image_name = image_name |
self.expected_hash = expected_hash |
self.actual_hash = actual_hash |
+ self.is_rebaselined = is_rebaselined |
class ExpectationsManager: |
@@ -228,13 +234,14 @@ class ExpectationsManager: |
# Invoke skpdiff with our downloaded images and place its results in the |
# temporary directory. |
- self.skpdiff_output_path = os.path.join(image_output_dir, |
+ self._skpdiff_output_path = os.path.join(image_output_dir, |
'skpdiff_output.json') |
skpdiff_cmd = SKPDIFF_INVOKE_FORMAT.format(self._skpdiff_path, |
- self.skpdiff_output_path, |
+ self._skpdiff_output_path, |
expected_image_dir, |
actual_image_dir) |
os.system(skpdiff_cmd) |
+ self._load_skpdiff_output() |
def _get_expectations(self): |
@@ -267,11 +274,25 @@ class ExpectationsManager: |
with open(updated_file_path, 'rb') as updated_file: |
updated_contents = updated_file.read() |
+ # Read the expected results on disk to determine what we've |
+ # already rebaselined. |
+ commited_contents = None |
+ with open(expected_file_path, 'rb') as expected_file: |
+ commited_contents = expected_file.read() |
+ |
# Find all expectations that did not match. |
expected_diff = differ.GenerateDiffDictFromStrings( |
expected_contents, |
updated_contents) |
+ # Generate a set of images that have already been rebaselined |
+ # onto disk. |
+ rebaselined_diff = differ.GenerateDiffDictFromStrings( |
+ expected_contents, |
+ commited_contents) |
+ |
+ rebaselined_set = set(rebaselined_diff.keys()) |
+ |
# The name of the device corresponds to the name of the folder |
# we are in. |
device_name = os.path.basename(root) |
@@ -280,7 +301,18 @@ class ExpectationsManager: |
for image_name, hashes in expected_diff.iteritems(): |
self._expectations.append( |
GMInstance(device_name, image_name, |
- hashes['old'], hashes['new'])) |
+ hashes['old'], hashes['new'], |
+ image_name in rebaselined_set)) |
+ |
+ def _load_skpdiff_output(self): |
+ """Loads the results of skpdiff and annotates them with whether they |
+ have already been rebaselined or not. The resulting data is store in |
+ self.skpdiff_records.""" |
+ self.skpdiff_records = None |
+ with open(self._skpdiff_output_path, 'rb') as skpdiff_output_file: |
+ self.skpdiff_records = json.load(skpdiff_output_file)['records'] |
+ for record in self.skpdiff_records: |
+ record['isRebaselined'] = self.image_map[record['baselinePath']][1].is_rebaselined |
def _download_expectation_images(self, expected_image_dir, actual_image_dir): |
@@ -346,23 +378,36 @@ class ExpectationsManager: |
# Write it out to disk using gm_json to keep the formatting consistent. |
gm_json.WriteToFile(expectations, json_path) |
- def use_hash_of(self, image_path): |
- """Determine the hash of the image at the path using the records, and |
- set it as the expected hash for its device and image config. |
+ def commit_rebaselines(self, rebaselines): |
+ """Sets the expected results file to use the hashes of the images in |
+ the rebaselines list. If a expected result image is not in rebaselines |
+ at all, the old hash will be used. |
- @param image_path The path of the image as it was stored in the output |
- of skpdiff_path |
+ @param rebaselines A list of image paths to use the hash of. |
""" |
+ # Reset all expectations to their old hashes because some of them may |
+ # have been set to the new hash by a previous call to this function. |
+ for expectation in self._expectations: |
+ expectation.is_rebaselined = False |
+ self._set_expected_hash(expectation.device_name, |
+ expectation.image_name, |
+ expectation.expected_hash) |
+ |
+ # Take all the images to rebaseline |
+ for image_path in rebaselines: |
+ # Get the metadata about the image at the path. |
+ is_actual, expectation = self.image_map[image_path] |
- # Get the metadata about the image at the path. |
- is_actual, expectation = self.image_map[image_path] |
+ expectation.is_rebaselined = is_actual |
+ expectation_hash = expectation.actual_hash if is_actual else\ |
+ expectation.expected_hash |
- expectation_hash = expectation.actual_hash if is_actual else\ |
- expectation.expected_hash |
+ # Write out that image's hash directly to the expected results file. |
+ self._set_expected_hash(expectation.device_name, |
+ expectation.image_name, |
+ expectation_hash) |
- # Write out that image's hash directly to the expected results file. |
- self._set_expected_hash(expectation.device_name, expectation.image_name, |
- expectation_hash) |
+ self._load_skpdiff_output() |
class SkPDiffHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
@@ -410,7 +455,15 @@ class SkPDiffHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
self.send_response(200) |
self.send_header('Content-type', MIME_TYPE_MAP['json']) |
self.end_headers() |
- self.wfile.write(self.server.skpdiff_output_json) |
+ |
+ # Add JSONP padding to the JSON because the web page expects it. It |
+ # expects it because it was designed to run with or without a web |
+ # server. Without a web server, the only way to load JSON is with |
+ # JSONP. |
+ skpdiff_records = self.server.expectations_manager.skpdiff_records |
+ self.wfile.write('var SkPDiffRecords = ') |
+ json.dump({'records': skpdiff_records}, self.wfile) |
+ self.wfile.write(';') |
return |
# Attempt to send static asset files first. |
@@ -427,10 +480,11 @@ class SkPDiffHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
self.send_error(404) |
def do_POST(self): |
- if self.path == '/set_hash': |
+ if self.path == '/commit_rebaselines': |
content_length = int(self.headers['Content-length']) |
request_data = json.loads(self.rfile.read(content_length)) |
- self.server.expectations_manager.use_hash_of(request_data['path']) |
+ rebaselines = request_data['rebaselines'] |
+ self.server.expectations_manager.commit_rebaselines(rebaselines) |
self.send_response(200) |
self.send_header('Content-type', 'application/json') |
self.end_headers() |
@@ -442,23 +496,11 @@ class SkPDiffHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
def run_server(expectations_manager, port=8080): |
- # Preload the skpdiff results file. This is so we can perform some |
- # processing on it. |
- skpdiff_output_json = '' |
- with open(expectations_manager.skpdiff_output_path, 'rb') as records_file: |
- skpdiff_output_json = records_file.read() |
- |
# It's important to parse the results file so that we can make a set of |
# images that the web page might request. |
- skpdiff_records = json.loads(skpdiff_output_json)['records'] |
+ skpdiff_records = expectations_manager.skpdiff_records |
image_set = get_image_set_from_skpdiff(skpdiff_records) |
- # Add JSONP padding to the JSON because the web page expects it. It expects |
- # it because it was designed to run with or without a web server. Without a |
- # web server, the only way to load JSON is with JSONP. |
- skpdiff_output_json = ('var SkPDiffRecords = ' + |
- json.dumps({'records': skpdiff_records}) + ';') |
- |
# Do not bind to interfaces other than localhost because the server will |
# attempt to serve files relative to the root directory as a last resort |
# before 404ing. This means all of your files can be accessed from this |
@@ -466,7 +508,6 @@ def run_server(expectations_manager, port=8080): |
server_address = ('127.0.0.1', port) |
http_server = BaseHTTPServer.HTTPServer(server_address, SkPDiffHandler) |
http_server.image_set = image_set |
- http_server.skpdiff_output_json = skpdiff_output_json |
http_server.expectations_manager = expectations_manager |
print('Navigate thine browser to: http://{}:{}/'.format(*server_address)) |
http_server.serve_forever() |