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

Side by Side Diff: tools/skpdiff/skpdiff_server.py

Issue 20654006: download and rebaseline images using server (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: actually saving the file edition Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/skpdiff/diff_viewer.js ('k') | tools/skpdiff/viewer.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 from __future__ import print_function 4 from __future__ import print_function
5 import argparse 5 import argparse
6 import BaseHTTPServer 6 import BaseHTTPServer
7 import json 7 import json
8 import os 8 import os
9 import os.path 9 import os.path
10 import re 10 import re
11 import subprocess
11 import sys 12 import sys
12 import tempfile 13 import tempfile
13 import urllib2 14 import urllib2
14 15
15 # Grab the script path because that is where all the static assets are 16 # Grab the script path because that is where all the static assets are
16 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 17 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
17 18
18 # Find the tools directory for python imports 19 # Find the tools directory for python imports
19 TOOLS_DIR = os.path.dirname(SCRIPT_DIR) 20 TOOLS_DIR = os.path.dirname(SCRIPT_DIR)
20 21
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 93
93 94
94 def download_gm_image(image_name, image_path, hash_val): 95 def download_gm_image(image_name, image_path, hash_val):
95 """Download the gm result into the given path. 96 """Download the gm result into the given path.
96 97
97 @param image_name The GM file name, for example imageblur_gpu.png. 98 @param image_name The GM file name, for example imageblur_gpu.png.
98 @param image_path Path to place the image. 99 @param image_path Path to place the image.
99 @param hash_val The hash value of the image. 100 @param hash_val The hash value of the image.
100 """ 101 """
101 102
102 # Seperate the test name from a image name 103 # Separate the test name from a image name
103 image_match = IMAGE_FILENAME_RE.match(image_name) 104 image_match = IMAGE_FILENAME_RE.match(image_name)
104 test_name = image_match.group(1) 105 test_name = image_match.group(1)
105 106
106 # Calculate the URL of the requested image 107 # Calculate the URL of the requested image
107 image_url = gm_json.CreateGmActualUrl( 108 image_url = gm_json.CreateGmActualUrl(
108 test_name, gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5, hash_val) 109 test_name, gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5, hash_val)
109 110
110 # Download the image as requested 111 # Download the image as requested
111 download_file(image_url, image_path) 112 download_file(image_url, image_path)
112 113
113 114
114 def download_changed_images(expectations_dir, expected_name, updated_name,
115 expected_image_dir, actual_image_dir):
116
117 """Download the expected and actual GMs that changed into the given paths.
118 Determining what changed will be done by comparing each expected_name JSON
119 results file to its corresponding updated_name JSON results file if it
120 exists.
121
122 @param expectations_dir The directory to traverse for results files. This
123 should resmble expectations/gm in the Skia trunk.
124 @param expected_name The name of the expected result files. These are
125 in the format of expected-results.json.
126 @param updated_name The name of the updated expected result files.
127 Normally this matches --expectations-filename-output for the
128 rebaseline.py tool.
129 @param expected_image_dir The directory to place downloaded expected images
130 into.
131 @param actual_image_dir The directory to place downloaded actual images
132 into.
133 """
134
135 differ = jsondiff.GMDiffer()
136
137 # Look through expectations for hashes that changed
138 for root, dirs, files in os.walk(expectations_dir):
139 for expectation_file in files:
140 # There are many files in the expectations directory. We only care
141 # about expected results.
142 if expectation_file != expected_name:
143 continue
144
145 # Get the name of the results file, and be sure there is an updated
146 # result to compare against. If there is not, there is no point in
147 # diffing this device.
148 expected_file_path = os.path.join(root, expected_name)
149 updated_file_path = os.path.join(root, updated_name)
150 if not os.path.isfile(updated_file_path):
151 continue
152
153 # Find all expectations that did not match.
154 expected_diff = differ.GenerateDiffDict(expected_file_path,
155 updated_file_path)
156
157 # The name of the device corresponds to the name of the folder we
158 # are in.
159 device_name = os.path.basename(root)
160
161 # Create name prefixes to store the devices old and new GM results
162 expected_image_prefix = os.path.join(expected_image_dir,
163 device_name) + '-'
164
165 actual_image_prefix = os.path.join(actual_image_dir,
166 device_name) + '-'
167
168 # Download each image that had a differing result
169 for image_name, hashes in expected_diff.iteritems():
170 print('Downloading', image_name, 'for device', device_name)
171 download_gm_image(image_name,
172 expected_image_prefix + image_name,
173 hashes['old'])
174 download_gm_image(image_name,
175 actual_image_prefix + image_name,
176 hashes['new'])
177
178
179 def get_image_set_from_skpdiff(skpdiff_records): 115 def get_image_set_from_skpdiff(skpdiff_records):
180 """Get the set of all images references in the given records. 116 """Get the set of all images references in the given records.
181 117
182 @param skpdiff_records An array of records, which are dictionary objects. 118 @param skpdiff_records An array of records, which are dictionary objects.
183 """ 119 """
184 expected_set = frozenset([r['baselinePath'] for r in skpdiff_records]) 120 expected_set = frozenset([r['baselinePath'] for r in skpdiff_records])
185 actual_set = frozenset([r['testPath'] for r in skpdiff_records]) 121 actual_set = frozenset([r['testPath'] for r in skpdiff_records])
186 return expected_set | actual_set 122 return expected_set | actual_set
187 123
188 124
125 def set_expected_hash_in_json(expected_results_json, image_name, hash_value):
126 """Set the expected hash for the object extracted from
127 expected-results.json. Note that this only work with bitmap-64bitMD5 hash
128 types.
129
130 @param expected_results_json The Python dictionary with the results to
131 modify.
132 @param image_name The name of the image to set the hash of.
133 @param hash_value The hash to set for the image.
134 """
135 expected_results = expected_results_json[gm_json.JSONKEY_EXPECTEDRESULTS]
136
137 if image_name in expected_results:
138 expected_results[image_name][gm_json.JSONKEY_EXPECTEDRESULTS_ALLOWEDDIGE STS][0][1] = hash_value
139 else:
140 expected_results[image_name] = {
141 gm_json.JSONKEY_EXPECTEDRESULTS_ALLOWEDDIGESTS:
142 [
143 [
144 gm_json.JSONKEY_HASHTYPE_BITMAP_64BITMD5,
145 hash_value
146 ]
147 ]
148 }
149
150
151 def get_head_version(path):
152 """Get the version of the file at the given path stored inside the HEAD of
153 the git repository. It is returned as a string.
154
155 @param path The path of the file whose HEAD is returned. It is assumed the
156 path is inside a git repo rooted at SKIA_ROOT_DIR.
157 """
158
159 # git-show will not work with absolute paths. This ensures we give it a path
160 # relative to the skia root.
161 git_path = os.path.relpath(path, SKIA_ROOT_DIR)
162 git_show_proc = subprocess.Popen(['git', 'show', 'HEAD:' + git_path],
163 stdout=subprocess.PIPE)
164
165 # When invoked outside a shell, git will output the last committed version
166 # of the file directly to stdout.
167 git_version_content, _ = git_show_proc.communicate()
168 return git_version_content
169
170
171 class GMInstance:
epoger 2013/08/06 15:26:43 Information about a particular GM test result: d
Zach Reizner 2013/08/07 13:56:02 Done.
172 def __init__(self,
173 device_name, image_name,
174 expected_hash, actual_hash):
175 self.device_name = device_name
176 self.image_name = image_name
177 self.expected_hash = expected_hash
178 self.actual_hash = actual_hash
179
180
181 class ExpectationsManager:
182 def __init__(self, expectations_dir, expected_name, updated_name,
183 skpdiff_path):
184 """
185 @param expectations_dir The directory to traverse for results files.
186 This should resmble expectations/gm in the Skia trunk.
187 @param expected_name The name of the expected result files. These
188 are in the format of expected-results.json.
189 @param updated_name The name of the updated expected result files.
190 Normally this matches --expectations-filename-output for the
191 rebaseline.py tool.
192 @param skpdiff_path The path used to execute the skpdiff command.
193 """
194 self._expectations_dir = expectations_dir
195 self._expected_name = expected_name
196 self._updated_name = updated_name
197 self._skpdiff_path = skpdiff_path
198 self._generate_gm_comparison()
199
200 def _generate_gm_comparison(self):
201 """Generate all the data needed to compare GMs:
202 - determine which GMs changed
203 - download the changed images
204 - compare them with skpdiff
205 """
206
207 # Get the expectations and compare them with actual hashes
208 self._get_expectations()
209
210
211 # Create a temporary file tree that makes sense for skpdiff to operate
212 # on.
213 image_output_dir = tempfile.mkdtemp('skpdiff')
214 expected_image_dir = os.path.join(image_output_dir, 'expected')
215 actual_image_dir = os.path.join(image_output_dir, 'actual')
216 os.mkdir(expected_image_dir)
217 os.mkdir(actual_image_dir)
218
219 # Download expected and actual images that differed into the temporary
220 # file tree.
221 self._download_expectation_images(expected_image_dir, actual_image_dir)
222
223 # Invoke skpdiff with our downloaded images and place its results in the
224 # temporary directory.
225 self.skpdiff_output_path = os.path.join(image_output_dir,
226 'skpdiff_output.json')
227 skpdiff_cmd = SKPDIFF_INVOKE_FORMAT.format(self._skpdiff_path,
228 self.skpdiff_output_path,
229 expected_image_dir,
230 actual_image_dir)
231 os.system(skpdiff_cmd)
232
233
234 def _get_expectations(self):
235 """Build an array of expectations that have changed with the actual
epoger 2013/08/06 15:26:43 Maybe this would be clearer? Fill self._expectati
Zach Reizner 2013/08/07 13:56:02 Done.
236 results.
237 """
238 differ = jsondiff.GMDiffer()
239 self._expectations = []
240 for root, dirs, files in os.walk(self._expectations_dir):
241 for expectation_file in files:
242 # There are many files in the expectations directory. We only
243 # care about expected results.
244 if expectation_file != self._expected_name:
245 continue
246
247 # Get the name of the results file, and be sure there is an
248 # updated result to compare against. If there is not, there is
249 # no point in diffing this device.
250 expected_file_path = os.path.join(root, self._expected_name)
251 updated_file_path = os.path.join(root, self._updated_name)
252 if not os.path.isfile(updated_file_path):
253 continue
254
255 # Always get the expected results from git because we may have
256 # changed them in a previous instance of the server.
257 expected_contents = get_head_version(expected_file_path)
258 updated_contents = None
259 with open(updated_file_path, 'rb') as updated_file:
260 updated_contents = updated_file.read()
261
262 # Find all expectations that did not match.
263 expected_diff = differ.GenerateDiffDictFromStrings(
264 expected_contents,
265 updated_contents)
266
267 # The name of the device corresponds to the name of the folder
268 # we are in.
269 device_name = os.path.basename(root)
270
271 # Download each image that had a differing result. We take care
epoger 2013/08/06 15:26:43 Not downloading anymore. Instead, maybe... Store
Zach Reizner 2013/08/07 13:56:02 Done.
272 # to store metadata about each image so that we know about an
273 # image from its path on disk alone. That is all we will know
274 # after skpdiff outputs its results.
275 for image_name, hashes in expected_diff.iteritems():
276 self._expectations.append(
277 GMInstance(device_name, image_name,
278 hashes['old'], hashes['new']))
279
280
281 def _download_expectation_images(self, expected_image_dir, actual_image_dir) :
282 """Download the expected and actual iamges for the _expectations array.
epoger 2013/08/06 15:26:43 iamges -> images
Zach Reizner 2013/08/07 13:56:02 Done.
283
284 @param expected_image_dir The directory to download expected images
285 into.
286 @param actual_image_dir The directory to download actual images into.
287 """
288 image_map = {}
289
290 # Look through expectations and download their images.
291 for expectation in self._expectations:
292 # Build appropriate paths to download the images into.
293 expected_image_path = os.path.join(expected_image_dir,
294 expectation.device_name + '-' +
295 expectation.image_name)
296
297 actual_image_path = os.path.join(actual_image_dir,
298 expectation.device_name + '-' +
299 expectation.image_name)
300
301 print('Downloading', expectation.image_name,
epoger 2013/08/06 15:26:43 A Python partisan would suggest: print 'Downloadi
302 'for device', expectation.device_name)
303
304 # Download images
305 download_gm_image(expectation.image_name,
306 expected_image_path,
307 expectation.expected_hash)
308
309 download_gm_image(expectation.image_name,
310 actual_image_path,
311 expectation.actual_hash)
312
313 # Annotate the expectations with where the images were downloaded
314 # to.
315 expectation.expected_image_path = expected_image_path
316 expectation.actual_image_path = actual_image_path
317
318 # Map the image paths back to the expectations.
319 image_map[expected_image_path] = (False, expectation)
320 image_map[actual_image_path] = (True, expectation)
321
322 self.image_map = image_map
323
324 def _set_expected_hash(self, device_name, image_name, hash_value):
325 """Set the expected hash for the image of the given device. This always
326 writes directly to the expected results file of the given device
327
328 @param device_name The name of the device to write the hash to.
329 @param image_name The name of the image whose hash to set.
330 @param hash_value The value of the hash to set.
331 """
332
333 # Retrieve the expected results file as it is in the working tree
334 json_path = os.path.join(self._expectations_dir, device_name,
335 self._expected_name)
336 expectations = gm_json.LoadFromFile(json_path)
337
338 # Set the specified hash.
339 set_expected_hash_in_json(expectations, image_name, hash_value)
340
341 # Write it out to disk using gm_json to keep the formatting consistent.
342 gm_json.WriteToFile(expectations, json_path)
343
344 def use_hash_of(self, image_path):
345 """Determine the hash of the image at the path using the records, and
346 set it as the expected hash for its device and image config.
347
348 @param image_path The path of the image as it was stored in the output
349 of skpdiff_path
350 """
351
352 # Get the metadata about the image at the path.
353 is_actual, expectation = self.image_map[image_path]
354
355 expectation_hash = expectation.actual_hash if is_actual else\
356 expectation.expected_hash
357
358 # Write out that image's hash directly to the expected results file.
359 self._set_expected_hash(expectation.device_name, expectation.image_name,
360 expectation_hash)
361
362
189 class SkPDiffHandler(BaseHTTPServer.BaseHTTPRequestHandler): 363 class SkPDiffHandler(BaseHTTPServer.BaseHTTPRequestHandler):
190 def send_file(self, file_path): 364 def send_file(self, file_path):
191 # Grab the extension if there is one 365 # Grab the extension if there is one
192 extension = os.path.splitext(file_path)[1] 366 extension = os.path.splitext(file_path)[1]
193 if len(extension) >= 1: 367 if len(extension) >= 1:
194 extension = extension[1:] 368 extension = extension[1:]
195 369
196 # Determine the MIME type of the file from its extension 370 # Determine the MIME type of the file from its extension
197 mime_type = MIME_TYPE_MAP.get(extension, MIME_TYPE_MAP['']) 371 mime_type = MIME_TYPE_MAP.get(extension, MIME_TYPE_MAP[''])
198 372
199 # Open the file and send it over HTTP 373 # Open the file and send it over HTTP
200 if os.path.isfile(file_path): 374 if os.path.isfile(file_path):
201 with open(file_path, 'rb') as sending_file: 375 with open(file_path, 'rb') as sending_file:
202 self.send_response(200) 376 self.send_response(200)
203 self.send_header('Content-type', mime_type) 377 self.send_header('Content-type', mime_type)
204 self.end_headers() 378 self.end_headers()
205 self.wfile.write(sending_file.read()) 379 self.wfile.write(sending_file.read())
206 else: 380 else:
207 self.send_error(404) 381 self.send_error(404)
208 382
209 def serve_if_in_dir(self, dir_path, file_path): 383 def serve_if_in_dir(self, dir_path, file_path):
210 # Determine if the file exists relative to the given dir_path AND exists 384 # Determine if the file exists relative to the given dir_path AND exists
211 # under the dir_path. This is to prevent accidentally serving files 385 # under the dir_path. This is to prevent accidentally serving files
212 # outside the directory intended using symlinks, or '../'. 386 # outside the directory intended using symlinks, or '../'.
213 real_path = os.path.normpath(os.path.join(dir_path, file_path)) 387 real_path = os.path.normpath(os.path.join(dir_path, file_path))
214 print(repr(real_path))
215 if os.path.commonprefix([real_path, dir_path]) == dir_path: 388 if os.path.commonprefix([real_path, dir_path]) == dir_path:
216 if os.path.isfile(real_path): 389 if os.path.isfile(real_path):
217 self.send_file(real_path) 390 self.send_file(real_path)
218 return True 391 return True
219 return False 392 return False
220 393
221 def do_GET(self): 394 def do_GET(self):
222 # Simple rewrite rule of the root path to 'viewer.html' 395 # Simple rewrite rule of the root path to 'viewer.html'
223 if self.path == '' or self.path == '/': 396 if self.path == '' or self.path == '/':
224 self.path = '/viewer.html' 397 self.path = '/viewer.html'
(...skipping 16 matching lines...) Expand all
241 414
242 # WARNING: Serving any file the user wants is incredibly insecure. Its 415 # WARNING: Serving any file the user wants is incredibly insecure. Its
243 # redeeming quality is that we only serve gm files on a white list. 416 # redeeming quality is that we only serve gm files on a white list.
244 if self.path in self.server.image_set: 417 if self.path in self.server.image_set:
245 self.send_file(self.path) 418 self.send_file(self.path)
246 return 419 return
247 420
248 # If no file to send was found, just give the standard 404 421 # If no file to send was found, just give the standard 404
249 self.send_error(404) 422 self.send_error(404)
250 423
424 def do_POST(self):
425 if self.path == '/set_hash':
426 content_length = int(self.headers['Content-length'])
427 request_data = json.loads(self.rfile.read(content_length))
428 self.server.expectations_manager.use_hash_of(request_data['path'])
429 self.send_response(200)
430 self.send_header('Content-type', 'application/json')
431 self.end_headers()
432 self.wfile.write('{"success":true}')
433 return
251 434
252 def run_server(skpdiff_output_path, port=8080): 435 # If the we have no handler for this path, give em' the 404
436 self.send_error(404)
437
438
439 def run_server(expectations_manager, port=8080):
253 # Preload the skpdiff results file. This is so we can perform some 440 # Preload the skpdiff results file. This is so we can perform some
254 # processing on it. 441 # processing on it.
255 skpdiff_output_json = '' 442 skpdiff_output_json = ''
256 with open(skpdiff_output_path, 'rb') as records_file: 443 with open(expectations_manager.skpdiff_output_path, 'rb') as records_file:
257 skpdiff_output_json = records_file.read() 444 skpdiff_output_json = records_file.read()
258 445
259 # It's important to parse the results file so that we can make a set of 446 # It's important to parse the results file so that we can make a set of
260 # images that the web page might request. 447 # images that the web page might request.
261 skpdiff_records = json.loads(skpdiff_output_json)['records'] 448 skpdiff_records = json.loads(skpdiff_output_json)['records']
262 image_set = get_image_set_from_skpdiff(skpdiff_records) 449 image_set = get_image_set_from_skpdiff(skpdiff_records)
263 450
264 # Add JSONP padding to the JSON because the web page expects it. It expects 451 # Add JSONP padding to the JSON because the web page expects it. It expects
265 # it because it was designed to run with or without a web server. Without a 452 # it because it was designed to run with or without a web server. Without a
266 # web server, the only way to load JSON is with JSONP. 453 # web server, the only way to load JSON is with JSONP.
267 skpdiff_output_json = 'var SkPDiffRecords = ' + skpdiff_output_json 454 skpdiff_output_json = ('var SkPDiffRecords = ' +
455 json.dumps({'records': skpdiff_records}) + ';')
268 456
269 # Do not bind to interfaces other than localhost because the server will 457 # Do not bind to interfaces other than localhost because the server will
270 # attempt to serve files relative to the root directory as a last resort 458 # attempt to serve files relative to the root directory as a last resort
271 # before 404ing. This means all of your files can be accessed from this 459 # before 404ing. This means all of your files can be accessed from this
272 # server, so DO NOT let this server listen to anything but localhost. 460 # server, so DO NOT let this server listen to anything but localhost.
273 server_address = ('127.0.0.1', port) 461 server_address = ('127.0.0.1', port)
274 http_server = BaseHTTPServer.HTTPServer(server_address, SkPDiffHandler) 462 http_server = BaseHTTPServer.HTTPServer(server_address, SkPDiffHandler)
275 http_server.image_set = image_set 463 http_server.image_set = image_set
276 http_server.skpdiff_output_json = skpdiff_output_json 464 http_server.skpdiff_output_json = skpdiff_output_json
277 print('Navigate thine browser to: http://{}:{}'.format(*server_address)) 465 http_server.expectations_manager = expectations_manager
466 print('Navigate thine browser to: http://{}:{}/'.format(*server_address))
278 http_server.serve_forever() 467 http_server.serve_forever()
279 468
280 469
281 def main(): 470 def main():
282 parser = argparse.ArgumentParser() 471 parser = argparse.ArgumentParser()
283 parser.add_argument('--port', '-p', metavar='PORT', 472 parser.add_argument('--port', '-p', metavar='PORT',
284 type=int, 473 type=int,
285 default=8080, 474 default=8080,
286 help='port to bind the server to; ' + 475 help='port to bind the server to; ' +
287 'defaults to %(default)s', 476 'defaults to %(default)s',
(...skipping 25 matching lines...) Expand all
313 'defaults to out/Release/skpdiff or out/Default/skpdiff' 502 'defaults to out/Release/skpdiff or out/Default/skpdiff'
314 ) 503 )
315 504
316 args = vars(parser.parse_args()) # Convert args into a python dict 505 args = vars(parser.parse_args()) # Convert args into a python dict
317 506
318 # Make sure we have access to an skpdiff binary 507 # Make sure we have access to an skpdiff binary
319 skpdiff_path = get_skpdiff_path(args['skpdiff_path']) 508 skpdiff_path = get_skpdiff_path(args['skpdiff_path'])
320 if skpdiff_path is None: 509 if skpdiff_path is None:
321 sys.exit(1) 510 sys.exit(1)
322 511
323 # Create a temporary file tree that makes sense for skpdiff.to operate on
324 image_output_dir = tempfile.mkdtemp('skpdiff')
325 expected_image_dir = os.path.join(image_output_dir, 'expected')
326 actual_image_dir = os.path.join(image_output_dir, 'actual')
327 os.mkdir(expected_image_dir)
328 os.mkdir(actual_image_dir)
329
330 # Print out the paths of things for easier debugging 512 # Print out the paths of things for easier debugging
331 print('script dir :', SCRIPT_DIR) 513 print('script dir :', SCRIPT_DIR)
332 print('tools dir :', TOOLS_DIR) 514 print('tools dir :', TOOLS_DIR)
333 print('root dir :', SKIA_ROOT_DIR) 515 print('root dir :', SKIA_ROOT_DIR)
334 print('expectations dir :', args['expectations_dir']) 516 print('expectations dir :', args['expectations_dir'])
335 print('skpdiff path :', skpdiff_path) 517 print('skpdiff path :', skpdiff_path)
336 print('tmp dir :', image_output_dir)
337 print('expected image dir :', expected_image_dir)
338 print('actual image dir :', actual_image_dir)
339 518
340 # Download expected and actual images that differed into the temporary file 519 expectations_manager = ExpectationsManager(args['expectations_dir'],
341 # tree. 520 args['expected'],
342 download_changed_images(args['expectations_dir'], 521 args['updated'],
343 args['expected'], args['updated'], 522 skpdiff_path)
344 expected_image_dir, actual_image_dir)
345 523
346 # Invoke skpdiff with our downloaded images and place its results in the 524 run_server(expectations_manager, port=args['port'])
347 # temporary directory.
348 skpdiff_output_path = os.path.join(image_output_dir, 'skpdiff_output.json')
349 skpdiff_cmd = SKPDIFF_INVOKE_FORMAT.format(skpdiff_path,
350 skpdiff_output_path,
351 expected_image_dir,
352 actual_image_dir)
353 os.system(skpdiff_cmd)
354
355 run_server(skpdiff_output_path, port=args['port'])
356 525
357 if __name__ == '__main__': 526 if __name__ == '__main__':
358 main() 527 main()
OLDNEW
« no previous file with comments | « tools/skpdiff/diff_viewer.js ('k') | tools/skpdiff/viewer.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698