Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import logging | 5 import logging |
| 6 import os | 6 import os |
| 7 import shutil | 7 import shutil |
| 8 import sys | 8 import sys |
| 9 import tempfile | 9 import tempfile |
| 10 | 10 |
| 11 _SRC_DIR = os.path.abspath(os.path.join( | 11 _SRC_DIR = os.path.abspath(os.path.join( |
| 12 os.path.dirname(__file__), '..', '..', '..')) | 12 os.path.dirname(__file__), '..', '..', '..')) |
| 13 | 13 |
| 14 sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil')) | 14 sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil')) |
| 15 from devil.android import device_utils | 15 from devil.android import device_utils |
| 16 | 16 |
| 17 import chrome_cache | 17 import chrome_cache |
| 18 import controller | 18 import controller |
| 19 import devtools_monitor | 19 import devtools_monitor |
| 20 import device_setup | 20 import device_setup |
| 21 import loading_trace | 21 import loading_trace |
| 22 | 22 |
| 23 | 23 |
| 24 # Standard filenames in the sandwich runner's output directory. | 24 # Standard filenames in the sandwich runner's output directory. |
| 25 ERROR_FILENAME = 'error' | |
| 25 TRACE_FILENAME = 'trace.json' | 26 TRACE_FILENAME = 'trace.json' |
| 26 VIDEO_FILENAME = 'video.mp4' | 27 VIDEO_FILENAME = 'video.mp4' |
| 27 WPR_LOG_FILENAME = 'wpr.log' | 28 WPR_LOG_FILENAME = 'wpr.log' |
| 28 | 29 |
| 29 # Memory dump category used to get memory metrics. | 30 # Memory dump category used to get memory metrics. |
| 30 MEMORY_DUMP_CATEGORY = 'disabled-by-default-memory-infra' | 31 MEMORY_DUMP_CATEGORY = 'disabled-by-default-memory-infra' |
| 31 | 32 |
| 32 # Devtools timeout of 1 minute to avoid websocket timeout on slow | 33 # Devtools timeout of 1 minute to avoid websocket timeout on slow |
| 33 # network condition. | 34 # network condition. |
| 34 _DEVTOOLS_TIMEOUT = 60 | 35 _DEVTOOLS_TIMEOUT = 60 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 | 134 |
| 134 def _RunNavigation(self, clear_cache, run_id=None): | 135 def _RunNavigation(self, clear_cache, run_id=None): |
| 135 """Run a page navigation to the given URL. | 136 """Run a page navigation to the given URL. |
| 136 | 137 |
| 137 Args: | 138 Args: |
| 138 clear_cache: Whether if the cache should be cleared before navigation. | 139 clear_cache: Whether if the cache should be cleared before navigation. |
| 139 run_id: Id of the run in the output directory. If it is None, then no | 140 run_id: Id of the run in the output directory. If it is None, then no |
| 140 trace or video will be saved. | 141 trace or video will be saved. |
| 141 """ | 142 """ |
| 142 run_path = None | 143 run_path = None |
| 143 if self.output_dir is not None and run_id is not None: | 144 if run_id is not None: |
|
pasko
2016/06/06 13:58:52
yeah, I always wondered why we needed SandwichRunn
gabadie
2016/06/06 14:03:55
No that was just to not record the trace for WPR r
| |
| 144 run_path = os.path.join(self.output_dir, str(run_id)) | 145 run_path = os.path.join(self.output_dir, str(run_id)) |
| 145 if not os.path.isdir(run_path): | 146 if not os.path.isdir(run_path): |
| 146 os.makedirs(run_path) | 147 os.makedirs(run_path) |
| 147 self._chrome_ctl.SetNetworkEmulation( | 148 self._chrome_ctl.SetNetworkEmulation( |
| 148 self._GetEmulatorNetworkCondition('browser')) | 149 self._GetEmulatorNetworkCondition('browser')) |
| 149 additional_categories = [] | 150 additional_categories = [] |
| 150 if self.record_memory_dumps: | 151 if self.record_memory_dumps: |
| 151 additional_categories = [MEMORY_DUMP_CATEGORY] | 152 additional_categories = [MEMORY_DUMP_CATEGORY] |
| 152 # TODO(gabadie): add a way to avoid recording a trace. | 153 # TODO(gabadie): add a way to avoid recording a trace. |
| 153 with self._chrome_ctl.Open() as connection: | 154 with self._chrome_ctl.Open() as connection: |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 184 clear_cache = False | 185 clear_cache = False |
| 185 if self.cache_operation == CacheOperation.CLEAR: | 186 if self.cache_operation == CacheOperation.CLEAR: |
| 186 clear_cache = True | 187 clear_cache = True |
| 187 elif self.cache_operation == CacheOperation.PUSH: | 188 elif self.cache_operation == CacheOperation.PUSH: |
| 188 self._chrome_ctl.PushBrowserCache(self._local_cache_directory_path) | 189 self._chrome_ctl.PushBrowserCache(self._local_cache_directory_path) |
| 189 elif self.cache_operation == CacheOperation.SAVE: | 190 elif self.cache_operation == CacheOperation.SAVE: |
| 190 clear_cache = run_id == 0 | 191 clear_cache = run_id == 0 |
| 191 self._RunNavigation(clear_cache=clear_cache, run_id=run_id) | 192 self._RunNavigation(clear_cache=clear_cache, run_id=run_id) |
| 192 break | 193 break |
| 193 except controller.ChromeControllerError as error: | 194 except controller.ChromeControllerError as error: |
| 195 if error.IsIntermittent() and attempt_id + 1 != self._ATTEMPT_COUNT: | |
| 196 dump_filename = 'intermittent_failure{}'.format(attempt_id) | |
| 197 dump_path = os.path.join(self.output_dir, str(run_id), dump_filename) | |
| 198 else: | |
| 199 dump_path = os.path.join(self.output_dir, ERROR_FILENAME) | |
| 200 with open(dump_path, 'w') as dump_output: | |
| 201 error.Dump(dump_output) | |
| 194 if not error.IsIntermittent(): | 202 if not error.IsIntermittent(): |
| 195 raise | 203 error.RaiseOriginal() |
|
pasko
2016/06/06 13:58:52
what does not work with raising ChromeControllerEr
gabadie
2016/06/06 14:03:55
'raise' would raise the previously catched excepti
mattcary
2016/06/06 14:37:09
A disadvantage of this approach is that we lose th
gabadie
2016/06/06 14:55:14
I don't see where the disadvantage is. The point o
| |
| 196 if self.output_dir is not None: | |
| 197 dump_path = os.path.join(self.output_dir, str(run_id), | |
| 198 'error{}'.format(attempt_id)) | |
| 199 with open(dump_path, 'w') as dump_output: | |
| 200 error.Dump(dump_output) | |
| 201 else: | 204 else: |
| 202 logging.error('Failed to navigate to %s after %d attemps' % \ | 205 logging.error('Failed to navigate to %s after %d attemps' % \ |
| 203 (self.url, self._ATTEMPT_COUNT)) | 206 (self.url, self._ATTEMPT_COUNT)) |
| 204 raise | 207 raise |
| 205 | 208 |
| 206 def _PullCacheFromDevice(self): | 209 def _PullCacheFromDevice(self): |
| 207 assert self.cache_operation == CacheOperation.SAVE | 210 assert self.cache_operation == CacheOperation.SAVE |
| 208 assert self.cache_archive_path, 'Need to specify where to save the cache' | 211 assert self.cache_archive_path, 'Need to specify where to save the cache' |
| 209 | 212 |
| 210 cache_directory_path = self._chrome_ctl.PullBrowserCache() | 213 cache_directory_path = self._chrome_ctl.PullBrowserCache() |
| 211 chrome_cache.ZipDirectoryContent( | 214 chrome_cache.ZipDirectoryContent( |
| 212 cache_directory_path, self.cache_archive_path) | 215 cache_directory_path, self.cache_archive_path) |
| 213 shutil.rmtree(cache_directory_path) | 216 shutil.rmtree(cache_directory_path) |
| 214 | 217 |
| 215 def Run(self): | 218 def Run(self): |
| 216 """SandwichRunner main entry point meant to be called once configured.""" | 219 """SandwichRunner main entry point meant to be called once configured.""" |
| 220 assert self.output_dir is not None | |
| 217 assert self._chrome_ctl == None | 221 assert self._chrome_ctl == None |
| 218 assert self._local_cache_directory_path == None | 222 assert self._local_cache_directory_path == None |
| 219 if self.output_dir: | 223 self._CleanTraceOutputDirectory() |
| 220 self._CleanTraceOutputDirectory() | |
| 221 | 224 |
| 222 if self.android_device: | 225 if self.android_device: |
| 223 self._chrome_ctl = controller.RemoteChromeController(self.android_device) | 226 self._chrome_ctl = controller.RemoteChromeController(self.android_device) |
| 224 else: | 227 else: |
| 225 self._chrome_ctl = controller.LocalChromeController() | 228 self._chrome_ctl = controller.LocalChromeController() |
| 226 self._chrome_ctl.AddChromeArguments(['--disable-infobars']) | 229 self._chrome_ctl.AddChromeArguments(['--disable-infobars']) |
| 227 self._chrome_ctl.AddChromeArguments(self.chrome_args) | 230 self._chrome_ctl.AddChromeArguments(self.chrome_args) |
| 228 if self.cache_operation == CacheOperation.SAVE: | 231 if self.cache_operation == CacheOperation.SAVE: |
| 229 self._chrome_ctl.SetSlowDeath() | 232 self._chrome_ctl.SetSlowDeath() |
| 230 | |
| 231 wpr_log_path = None | |
| 232 if self.output_dir: | |
| 233 wpr_log_path = os.path.join(self.output_dir, WPR_LOG_FILENAME) | |
| 234 | |
| 235 try: | 233 try: |
| 236 if self.cache_operation == CacheOperation.PUSH: | 234 if self.cache_operation == CacheOperation.PUSH: |
| 237 assert os.path.isfile(self.cache_archive_path) | 235 assert os.path.isfile(self.cache_archive_path) |
| 238 self._local_cache_directory_path = tempfile.mkdtemp(suffix='.cache') | 236 self._local_cache_directory_path = tempfile.mkdtemp(suffix='.cache') |
| 239 chrome_cache.UnzipDirectoryContent( | 237 chrome_cache.UnzipDirectoryContent( |
| 240 self.cache_archive_path, self._local_cache_directory_path) | 238 self.cache_archive_path, self._local_cache_directory_path) |
| 241 | 239 |
| 242 with self._chrome_ctl.OpenWprHost(self.wpr_archive_path, | 240 with self._chrome_ctl.OpenWprHost(self.wpr_archive_path, |
| 243 record=self.wpr_record, | 241 record=self.wpr_record, |
| 244 network_condition_name=self._GetEmulatorNetworkCondition('wpr'), | 242 network_condition_name=self._GetEmulatorNetworkCondition('wpr'), |
| 245 disable_script_injection=self.disable_wpr_script_injection, | 243 disable_script_injection=self.disable_wpr_script_injection, |
| 246 out_log_path=wpr_log_path): | 244 out_log_path=os.path.join(self.output_dir, WPR_LOG_FILENAME)): |
| 247 for repeat_id in xrange(self.repeat): | 245 for repeat_id in xrange(self.repeat): |
| 248 self._RunUrl(run_id=repeat_id) | 246 self._RunUrl(run_id=repeat_id) |
| 249 finally: | 247 finally: |
| 250 if self._local_cache_directory_path: | 248 if self._local_cache_directory_path: |
| 251 shutil.rmtree(self._local_cache_directory_path) | 249 shutil.rmtree(self._local_cache_directory_path) |
| 252 self._local_cache_directory_path = None | 250 self._local_cache_directory_path = None |
| 253 if self.cache_operation == CacheOperation.SAVE: | 251 if self.cache_operation == CacheOperation.SAVE: |
| 254 self._PullCacheFromDevice() | 252 self._PullCacheFromDevice() |
| 255 | 253 |
| 256 self._chrome_ctl = None | 254 self._chrome_ctl = None |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 268 if not os.path.isdir(repeat_dir): | 266 if not os.path.isdir(repeat_dir): |
| 269 continue | 267 continue |
| 270 try: | 268 try: |
| 271 repeat_id = int(node_name) | 269 repeat_id = int(node_name) |
| 272 except ValueError: | 270 except ValueError: |
| 273 continue | 271 continue |
| 274 yield repeat_id, repeat_dir | 272 yield repeat_id, repeat_dir |
| 275 repeated_run_count += 1 | 273 repeated_run_count += 1 |
| 276 assert repeated_run_count > 0, ('Error: not a sandwich runner output ' | 274 assert repeated_run_count > 0, ('Error: not a sandwich runner output ' |
| 277 'directory: {}').format(runner_output_dir) | 275 'directory: {}').format(runner_output_dir) |
| OLD | NEW |