OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 """ | 3 """ |
4 Copyright 2013 Google Inc. | 4 Copyright 2013 Google Inc. |
5 | 5 |
6 Use of this source code is governed by a BSD-style license that can be | 6 Use of this source code is governed by a BSD-style license that can be |
7 found in the LICENSE file. | 7 found in the LICENSE file. |
8 | 8 |
9 HTTP server for our HTML rebaseline viewer. | 9 HTTP server for our HTML rebaseline viewer. |
10 """ | 10 """ |
11 | 11 |
12 # System-level imports | 12 # System-level imports |
13 import argparse | 13 import argparse |
14 import BaseHTTPServer | 14 import BaseHTTPServer |
15 import json | 15 import json |
16 import logging | 16 import logging |
17 import os | 17 import os |
18 import posixpath | 18 import posixpath |
19 import re | 19 import re |
20 import shutil | 20 import shutil |
21 import socket | 21 import socket |
22 import subprocess | 22 import subprocess |
23 import thread | 23 import thread |
24 import threading | 24 import threading |
25 import time | 25 import time |
| 26 import urllib |
26 import urlparse | 27 import urlparse |
27 | 28 |
28 # Must fix up PYTHONPATH before importing from within Skia | 29 # Must fix up PYTHONPATH before importing from within Skia |
29 import fix_pythonpath # pylint: disable=W0611 | 30 import fix_pythonpath # pylint: disable=W0611 |
30 | 31 |
31 # Imports from within Skia | 32 # Imports from within Skia |
32 from py.utils import gs_utils | 33 from py.utils import gs_utils |
| 34 import buildbot_globals |
33 import gm_json | 35 import gm_json |
34 | 36 |
35 # Imports from local dir | 37 # Imports from local dir |
36 # | 38 # |
37 # pylint: disable=C0301 | 39 # pylint: disable=C0301 |
38 # Note: we import results under a different name, to avoid confusion with the | 40 # Note: we import results under a different name, to avoid confusion with the |
39 # Server.results() property. See discussion at | 41 # Server.results() property. See discussion at |
40 # https://codereview.chromium.org/195943004/diff/1/gm/rebaseline_server/server.p
y#newcode44 | 42 # https://codereview.chromium.org/195943004/diff/1/gm/rebaseline_server/server.p
y#newcode44 |
41 # pylint: enable=C0301 | 43 # pylint: enable=C0301 |
42 import compare_configs | 44 import compare_configs |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 LIVE_PARAM__DOWNLOAD_ONLY_DIFFERING = 'downloadOnlyDifferingImages' | 94 LIVE_PARAM__DOWNLOAD_ONLY_DIFFERING = 'downloadOnlyDifferingImages' |
93 LIVE_PARAM__SET_A_DIR = 'setADir' | 95 LIVE_PARAM__SET_A_DIR = 'setADir' |
94 LIVE_PARAM__SET_A_SECTION = 'setASection' | 96 LIVE_PARAM__SET_A_SECTION = 'setASection' |
95 LIVE_PARAM__SET_B_DIR = 'setBDir' | 97 LIVE_PARAM__SET_B_DIR = 'setBDir' |
96 LIVE_PARAM__SET_B_SECTION = 'setBSection' | 98 LIVE_PARAM__SET_B_SECTION = 'setBSection' |
97 | 99 |
98 # How often (in seconds) clients should reload while waiting for initial | 100 # How often (in seconds) clients should reload while waiting for initial |
99 # results to load. | 101 # results to load. |
100 RELOAD_INTERVAL_UNTIL_READY = 10 | 102 RELOAD_INTERVAL_UNTIL_READY = 10 |
101 | 103 |
102 SUMMARY_TYPES = [ | 104 _GM_SUMMARY_TYPES = [ |
103 results_mod.KEY__HEADER__RESULTS_FAILURES, | 105 results_mod.KEY__HEADER__RESULTS_FAILURES, |
104 results_mod.KEY__HEADER__RESULTS_ALL, | 106 results_mod.KEY__HEADER__RESULTS_ALL, |
105 ] | 107 ] |
106 # If --compare-configs is specified, compare these configs. | 108 # If --compare-configs is specified, compare these configs. |
107 CONFIG_PAIRS_TO_COMPARE = [('8888', 'gpu')] | 109 CONFIG_PAIRS_TO_COMPARE = [('8888', 'gpu')] |
108 | 110 |
| 111 # SKP results that are available to compare. |
| 112 # |
| 113 # TODO(stephana): We don't actually want to maintain this list of platforms. |
| 114 # We are just putting them in here for now, as "convenience" links for testing |
| 115 # SKP diffs. |
| 116 # Ultimately, we will depend on buildbot steps linking to their own diffs on |
| 117 # the shared rebaseline_server instance. |
| 118 _SKP_BASE_GS_URL = 'gs://' + buildbot_globals.Get('skp_summaries_bucket') |
| 119 _SKP_PLATFORMS = [ |
| 120 'Test-Mac10.8-MacMini4.1-GeForce320M-x86_64-Debug', |
| 121 'Test-Ubuntu12-ShuttleA-GTX660-x86-Release', |
| 122 ] |
| 123 |
109 _HTTP_HEADER_CONTENT_LENGTH = 'Content-Length' | 124 _HTTP_HEADER_CONTENT_LENGTH = 'Content-Length' |
110 _HTTP_HEADER_CONTENT_TYPE = 'Content-Type' | 125 _HTTP_HEADER_CONTENT_TYPE = 'Content-Type' |
111 | 126 |
112 _SERVER = None # This gets filled in by main() | 127 _SERVER = None # This gets filled in by main() |
113 | 128 |
114 | 129 |
115 def _run_command(args, directory): | 130 def _run_command(args, directory): |
116 """Runs a command and returns stdout as a single string. | 131 """Runs a command and returns stdout as a single string. |
117 | 132 |
118 Args: | 133 Args: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 config_pairs: what pairs of configs (if any) we compare actual results of | 178 config_pairs: what pairs of configs (if any) we compare actual results of |
164 """ | 179 """ |
165 dir_path = os.path.dirname(file_path) | 180 dir_path = os.path.dirname(file_path) |
166 if not os.path.isdir(dir_path): | 181 if not os.path.isdir(dir_path): |
167 os.makedirs(dir_path) | 182 os.makedirs(dir_path) |
168 with open(file_path, 'w') as file_handle: | 183 with open(file_path, 'w') as file_handle: |
169 file_handle.write( | 184 file_handle.write( |
170 '<!DOCTYPE html><html>' | 185 '<!DOCTYPE html><html>' |
171 '<head><title>rebaseline_server</title></head>' | 186 '<head><title>rebaseline_server</title></head>' |
172 '<body><ul>') | 187 '<body><ul>') |
173 if SUMMARY_TYPES: | 188 |
174 file_handle.write('<li>Expectations vs Actuals</li><ul>') | 189 if _GM_SUMMARY_TYPES: |
175 for summary_type in SUMMARY_TYPES: | 190 file_handle.write('<li>GM Expectations vs Actuals</li><ul>') |
| 191 for summary_type in _GM_SUMMARY_TYPES: |
176 file_handle.write( | 192 file_handle.write( |
177 '<li><a href="/{static_directive}/view.html#/view.html?' | 193 '\n<li><a href="/{static_directive}/view.html#/view.html?' |
178 'resultsToLoad=/{results_directive}/{summary_type}">' | 194 'resultsToLoad=/{results_directive}/{summary_type}">' |
179 '{summary_type}</a></li>'.format( | 195 '{summary_type}</a></li>'.format( |
180 results_directive=GET__PRECOMPUTED_RESULTS, | 196 results_directive=GET__PRECOMPUTED_RESULTS, |
181 static_directive=GET__STATIC_CONTENTS, | 197 static_directive=GET__STATIC_CONTENTS, |
182 summary_type=summary_type)) | 198 summary_type=summary_type)) |
183 file_handle.write('</ul>') | 199 file_handle.write('</ul>') |
| 200 |
184 if config_pairs: | 201 if config_pairs: |
185 file_handle.write('<li>Comparing configs within actual results</li><ul>') | 202 file_handle.write( |
| 203 '\n<li>Comparing configs within actual GM results</li><ul>') |
186 for config_pair in config_pairs: | 204 for config_pair in config_pairs: |
187 file_handle.write('<li>%s vs %s:' % config_pair) | 205 file_handle.write('<li>%s vs %s:' % config_pair) |
188 for summary_type in SUMMARY_TYPES: | 206 for summary_type in _GM_SUMMARY_TYPES: |
189 file_handle.write( | 207 file_handle.write( |
190 ' <a href="/%s/view.html#/view.html?' | 208 ' <a href="/%s/view.html#/view.html?' |
191 'resultsToLoad=/%s/%s/%s-vs-%s_%s.json">%s</a>' % ( | 209 'resultsToLoad=/%s/%s/%s-vs-%s_%s.json">%s</a>' % ( |
192 GET__STATIC_CONTENTS, GET__STATIC_CONTENTS, | 210 GET__STATIC_CONTENTS, GET__STATIC_CONTENTS, |
193 GENERATED_JSON_SUBDIR, config_pair[0], config_pair[1], | 211 GENERATED_JSON_SUBDIR, config_pair[0], config_pair[1], |
194 summary_type, summary_type)) | 212 summary_type, summary_type)) |
195 file_handle.write('</li>') | 213 file_handle.write('</li>') |
196 file_handle.write('</ul>') | 214 file_handle.write('</ul>') |
197 file_handle.write('</ul></body></html>') | 215 |
| 216 if _SKP_PLATFORMS: |
| 217 file_handle.write('\n<li>Rendered SKPs:<ul>') |
| 218 for builder in _SKP_PLATFORMS: |
| 219 file_handle.write( |
| 220 '\n<li><a href="../live-view.html#live-view.html?%s">' % |
| 221 urllib.urlencode({ |
| 222 LIVE_PARAM__SET_A_SECTION: |
| 223 gm_json.JSONKEY_EXPECTEDRESULTS, |
| 224 LIVE_PARAM__SET_A_DIR: |
| 225 posixpath.join(_SKP_BASE_GS_URL, builder), |
| 226 LIVE_PARAM__SET_B_SECTION: |
| 227 gm_json.JSONKEY_ACTUALRESULTS, |
| 228 LIVE_PARAM__SET_B_DIR: |
| 229 posixpath.join(_SKP_BASE_GS_URL, builder), |
| 230 })) |
| 231 file_handle.write('expected vs actuals on %s</a></li>' % builder) |
| 232 file_handle.write( |
| 233 '\n<li><a href="../live-view.html#live-view.html?%s">' % |
| 234 urllib.urlencode({ |
| 235 LIVE_PARAM__SET_A_SECTION: |
| 236 gm_json.JSONKEY_ACTUALRESULTS, |
| 237 LIVE_PARAM__SET_A_DIR: |
| 238 posixpath.join(_SKP_BASE_GS_URL, _SKP_PLATFORMS[0]), |
| 239 LIVE_PARAM__SET_B_SECTION: |
| 240 gm_json.JSONKEY_ACTUALRESULTS, |
| 241 LIVE_PARAM__SET_B_DIR: |
| 242 posixpath.join(_SKP_BASE_GS_URL, _SKP_PLATFORMS[1]), |
| 243 })) |
| 244 file_handle.write('actuals on %s vs %s</a></li>' % ( |
| 245 _SKP_PLATFORMS[0], _SKP_PLATFORMS[1])) |
| 246 file_handle.write('</li>') |
| 247 |
| 248 file_handle.write('\n</ul></body></html>') |
198 | 249 |
199 | 250 |
200 class Server(object): | 251 class Server(object): |
201 """ HTTP server for our HTML rebaseline viewer. """ | 252 """ HTTP server for our HTML rebaseline viewer. """ |
202 | 253 |
203 def __init__(self, | 254 def __init__(self, |
204 actuals_dir=DEFAULT_ACTUALS_DIR, | 255 actuals_dir=DEFAULT_ACTUALS_DIR, |
205 json_filename=DEFAULT_JSON_FILENAME, | 256 json_filename=DEFAULT_JSON_FILENAME, |
206 gm_summaries_bucket=DEFAULT_GM_SUMMARIES_BUCKET, | 257 gm_summaries_bucket=DEFAULT_GM_SUMMARIES_BUCKET, |
207 port=DEFAULT_PORT, export=False, editable=True, | 258 port=DEFAULT_PORT, export=False, editable=True, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 for config_pair in self._config_pairs: | 450 for config_pair in self._config_pairs: |
400 config_comparisons = compare_configs.ConfigComparisons( | 451 config_comparisons = compare_configs.ConfigComparisons( |
401 configs=config_pair, | 452 configs=config_pair, |
402 actuals_root=self._actuals_dir, | 453 actuals_root=self._actuals_dir, |
403 generated_images_root=os.path.join( | 454 generated_images_root=os.path.join( |
404 PARENT_DIRECTORY, STATIC_CONTENTS_SUBDIR, | 455 PARENT_DIRECTORY, STATIC_CONTENTS_SUBDIR, |
405 GENERATED_IMAGES_SUBDIR), | 456 GENERATED_IMAGES_SUBDIR), |
406 diff_base_url=posixpath.join( | 457 diff_base_url=posixpath.join( |
407 os.pardir, GENERATED_IMAGES_SUBDIR), | 458 os.pardir, GENERATED_IMAGES_SUBDIR), |
408 builder_regex_list=self._builder_regex_list) | 459 builder_regex_list=self._builder_regex_list) |
409 for summary_type in SUMMARY_TYPES: | 460 for summary_type in _GM_SUMMARY_TYPES: |
410 gm_json.WriteToFile( | 461 gm_json.WriteToFile( |
411 config_comparisons.get_packaged_results_of_type( | 462 config_comparisons.get_packaged_results_of_type( |
412 results_type=summary_type), | 463 results_type=summary_type), |
413 os.path.join( | 464 os.path.join( |
414 json_dir, '%s-vs-%s_%s.json' % ( | 465 json_dir, '%s-vs-%s_%s.json' % ( |
415 config_pair[0], config_pair[1], summary_type))) | 466 config_pair[0], config_pair[1], summary_type))) |
416 | 467 |
417 def _result_loader(self, reload_seconds=0): | 468 def _result_loader(self, reload_seconds=0): |
418 """ Call self.update_results(), either once or periodically. | 469 """ Call self.update_results(), either once or periodically. |
419 | 470 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 reload_seconds=args.reload, config_pairs=config_pairs, | 870 reload_seconds=args.reload, config_pairs=config_pairs, |
820 builder_regex_list=args.builders, boto_file_path=args.boto, | 871 builder_regex_list=args.builders, boto_file_path=args.boto, |
821 imagediffdb_threads=args.threads) | 872 imagediffdb_threads=args.threads) |
822 if args.truncate: | 873 if args.truncate: |
823 _SERVER.truncate_results = True | 874 _SERVER.truncate_results = True |
824 _SERVER.run() | 875 _SERVER.run() |
825 | 876 |
826 | 877 |
827 if __name__ == '__main__': | 878 if __name__ == '__main__': |
828 main() | 879 main() |
OLD | NEW |