| OLD | NEW |
| 1 #! /usr/bin/env python | 1 #! /usr/bin/env python |
| 2 # Copyright 2016 The Chromium Authors. All rights reserved. | 2 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Instructs Chrome to load series of web pages and reports results. | 6 """Instructs Chrome to load series of web pages and reports results. |
| 7 | 7 |
| 8 When running Chrome is sandwiched between preprocessed disk caches and | 8 When running Chrome is sandwiched between preprocessed disk caches and |
| 9 WepPageReplay serving all connections. | 9 WepPageReplay serving all connections. |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 _SRC_DIR = os.path.abspath(os.path.join( | 26 _SRC_DIR = os.path.abspath(os.path.join( |
| 27 os.path.dirname(__file__), '..', '..', '..')) | 27 os.path.dirname(__file__), '..', '..', '..')) |
| 28 | 28 |
| 29 sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil')) | 29 sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil')) |
| 30 from devil.android import device_utils | 30 from devil.android import device_utils |
| 31 | 31 |
| 32 sys.path.append(os.path.join(_SRC_DIR, 'build', 'android')) | 32 sys.path.append(os.path.join(_SRC_DIR, 'build', 'android')) |
| 33 from pylib import constants | 33 from pylib import constants |
| 34 import devil_chromium | 34 import devil_chromium |
| 35 | 35 |
| 36 import chrome_setup |
| 36 import device_setup | 37 import device_setup |
| 37 import devtools_monitor | 38 import devtools_monitor |
| 38 import options | 39 import options |
| 39 import page_track | 40 import page_track |
| 40 import pull_sandwich_metrics | 41 import pull_sandwich_metrics |
| 41 import trace_recorder | 42 import trace_recorder |
| 42 import tracing | 43 import tracing |
| 43 | 44 |
| 44 | 45 |
| 45 # Use options layer to access constants. | 46 # Use options layer to access constants. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 58 _REAL_INDEX_FILE_NAME = 'the-real-index' | 59 _REAL_INDEX_FILE_NAME = 'the-real-index' |
| 59 | 60 |
| 60 # An estimate of time to wait for the device to become idle after expensive | 61 # An estimate of time to wait for the device to become idle after expensive |
| 61 # operations, such as opening the launcher activity. | 62 # operations, such as opening the launcher activity. |
| 62 _TIME_TO_DEVICE_IDLE_SECONDS = 2 | 63 _TIME_TO_DEVICE_IDLE_SECONDS = 2 |
| 63 | 64 |
| 64 | 65 |
| 65 def _RemoteCacheDirectory(): | 66 def _RemoteCacheDirectory(): |
| 66 return '/data/data/{}/cache/Cache'.format(OPTIONS.chrome_package_name) | 67 return '/data/data/{}/cache/Cache'.format(OPTIONS.chrome_package_name) |
| 67 | 68 |
| 69 # Devtools timeout of 1 minute to avoid websocket timeout on slow |
| 70 # network condition. |
| 71 _DEVTOOLS_TIMEOUT = 60 |
| 72 |
| 68 | 73 |
| 69 def _ReadUrlsFromJobDescription(job_name): | 74 def _ReadUrlsFromJobDescription(job_name): |
| 70 """Retrieves the list of URLs associated with the job name.""" | 75 """Retrieves the list of URLs associated with the job name.""" |
| 71 try: | 76 try: |
| 72 # Extra sugar: attempt to load from a relative path. | 77 # Extra sugar: attempt to load from a relative path. |
| 73 json_file_name = os.path.join(os.path.dirname(__file__), _JOB_SEARCH_PATH, | 78 json_file_name = os.path.join(os.path.dirname(__file__), _JOB_SEARCH_PATH, |
| 74 job_name) | 79 job_name) |
| 75 with open(json_file_name) as f: | 80 with open(json_file_name) as f: |
| 76 json_data = json.load(f) | 81 json_data = json.load(f) |
| 77 except IOError: | 82 except IOError: |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 directory_path = os.path.join(output_directories_path, dirname) | 256 directory_path = os.path.join(output_directories_path, dirname) |
| 252 if not os.path.isdir(directory_path): | 257 if not os.path.isdir(directory_path): |
| 253 continue | 258 continue |
| 254 try: | 259 try: |
| 255 int(dirname) | 260 int(dirname) |
| 256 except ValueError: | 261 except ValueError: |
| 257 continue | 262 continue |
| 258 shutil.rmtree(directory_path) | 263 shutil.rmtree(directory_path) |
| 259 | 264 |
| 260 | 265 |
| 261 def main(): | 266 def _ArgumentParser(): |
| 262 logging.basicConfig(level=logging.INFO) | 267 """Build a command line argument's parser. |
| 263 devil_chromium.Initialize() | 268 """ |
| 264 | |
| 265 # Don't give the argument yet. All we are interested in for now is accessing | |
| 266 # the default values of OPTIONS. | |
| 267 OPTIONS.ParseArgs([]) | |
| 268 | |
| 269 parser = argparse.ArgumentParser() | 269 parser = argparse.ArgumentParser() |
| 270 parser.add_argument('--job', required=True, | 270 parser.add_argument('--job', required=True, |
| 271 help='JSON file with job description.') | 271 help='JSON file with job description.') |
| 272 parser.add_argument('--output', required=True, | 272 parser.add_argument('--output', required=True, |
| 273 help='Name of output directory to create.') | 273 help='Name of output directory to create.') |
| 274 parser.add_argument('--repeat', default=1, type=int, | 274 parser.add_argument('--repeat', default=1, type=int, |
| 275 help='How many times to run the job') | 275 help='How many times to run the job') |
| 276 parser.add_argument('--cache-op', | 276 parser.add_argument('--cache-op', |
| 277 choices=['clear', 'save', 'push', 'reload'], | 277 choices=['clear', 'save', 'push', 'reload'], |
| 278 default='clear', | 278 default='clear', |
| 279 help='Configures cache operation to do before launching ' | 279 help='Configures cache operation to do before launching ' |
| 280 +'Chrome. (Default is clear).') | 280 +'Chrome. (Default is clear).') |
| 281 parser.add_argument('--wpr-archive', default=None, type=str, | 281 parser.add_argument('--wpr-archive', default=None, type=str, |
| 282 help='Web page replay archive to load job\'s urls from.') | 282 help='Web page replay archive to load job\'s urls from.') |
| 283 parser.add_argument('--wpr-record', default=False, action='store_true', | 283 parser.add_argument('--wpr-record', default=False, action='store_true', |
| 284 help='Record web page replay archive.') | 284 help='Record web page replay archive.') |
| 285 parser.add_argument('--disable-wpr-script-injection', default=False, | 285 parser.add_argument('--disable-wpr-script-injection', default=False, |
| 286 action='store_true', | 286 action='store_true', |
| 287 help='Disable WPR default script injection such as ' + | 287 help='Disable WPR default script injection such as ' + |
| 288 'overriding javascript\'s Math.random() and Date() ' + | 288 'overriding javascript\'s Math.random() and Date() ' + |
| 289 'with deterministic implementations.') | 289 'with deterministic implementations.') |
| 290 args = parser.parse_args() | 290 parser.add_argument('--network-condition', default=None, |
| 291 choices=sorted(chrome_setup.NETWORK_CONDITIONS.keys()), |
| 292 help='Set a network profile.') |
| 293 parser.add_argument('--network-emulator', default='browser', |
| 294 choices=['browser', 'wpr'], |
| 295 help='Set which component is emulating the network condition.' + |
| 296 ' (Default to browser)') |
| 297 return parser |
| 298 |
| 299 |
| 300 def main(): |
| 301 logging.basicConfig(level=logging.INFO) |
| 302 devil_chromium.Initialize() |
| 303 |
| 304 # Don't give the argument yet. All we are interested in for now is accessing |
| 305 # the default values of OPTIONS. |
| 306 OPTIONS.ParseArgs([]) |
| 307 |
| 308 args = _ArgumentParser().parse_args() |
| 291 | 309 |
| 292 if not os.path.isdir(args.output): | 310 if not os.path.isdir(args.output): |
| 293 try: | 311 try: |
| 294 os.makedirs(args.output) | 312 os.makedirs(args.output) |
| 295 except OSError: | 313 except OSError: |
| 296 logging.error('Cannot create directory for results: %s' % args.output) | 314 logging.error('Cannot create directory for results: %s' % args.output) |
| 297 raise | 315 raise |
| 298 else: | 316 else: |
| 299 _CleanPreviousTraces(args.output) | 317 _CleanPreviousTraces(args.output) |
| 300 | 318 |
| 301 run_infos = { | 319 run_infos = { |
| 302 'cache-op': args.cache_op, | 320 'cache-op': args.cache_op, |
| 303 'job': args.job, | 321 'job': args.job, |
| 304 'urls': [] | 322 'urls': [] |
| 305 } | 323 } |
| 306 job_urls = _ReadUrlsFromJobDescription(args.job) | 324 job_urls = _ReadUrlsFromJobDescription(args.job) |
| 307 device = device_utils.DeviceUtils.HealthyDevices()[0] | 325 device = device_utils.DeviceUtils.HealthyDevices()[0] |
| 308 local_cache_archive_path = os.path.join(args.output, 'cache.zip') | 326 local_cache_archive_path = os.path.join(args.output, 'cache.zip') |
| 309 local_cache_directory_path = None | 327 local_cache_directory_path = None |
| 328 wpr_network_condition_name = None |
| 329 browser_network_condition_name = None |
| 330 if args.network_emulator == 'wpr': |
| 331 wpr_network_condition_name = args.network_condition |
| 332 elif args.network_emulator == 'browser': |
| 333 browser_network_condition_name = args.network_condition |
| 334 else: |
| 335 assert False |
| 310 | 336 |
| 311 if args.cache_op == 'push': | 337 if args.cache_op == 'push': |
| 312 assert os.path.isfile(local_cache_archive_path) | 338 assert os.path.isfile(local_cache_archive_path) |
| 313 local_cache_directory_path = tempfile.mkdtemp(suffix='.cache') | 339 local_cache_directory_path = tempfile.mkdtemp(suffix='.cache') |
| 314 _UnzipDirectoryContent(local_cache_archive_path, local_cache_directory_path) | 340 _UnzipDirectoryContent(local_cache_archive_path, local_cache_directory_path) |
| 315 | 341 |
| 316 with device_setup.WprHost(device, args.wpr_archive, args.wpr_record, | 342 with device_setup.WprHost(device, args.wpr_archive, |
| 317 args.disable_wpr_script_injection) as additional_flags: | 343 record=args.wpr_record, |
| 344 network_condition_name=wpr_network_condition_name, |
| 345 disable_script_injection=args.disable_wpr_script_injection |
| 346 ) as additional_flags: |
| 318 def _RunNavigation(url, clear_cache, trace_id): | 347 def _RunNavigation(url, clear_cache, trace_id): |
| 319 with device_setup.DeviceConnection( | 348 with device_setup.DeviceConnection( |
| 320 device=device, | 349 device=device, |
| 321 additional_flags=additional_flags) as connection: | 350 additional_flags=additional_flags) as connection: |
| 351 additional_metadata = {} |
| 352 if browser_network_condition_name: |
| 353 additional_metadata = chrome_setup.SetUpEmulationAndReturnMetadata( |
| 354 connection=connection, |
| 355 emulated_device_name=None, |
| 356 emulated_network_name=browser_network_condition_name) |
| 322 loading_trace = trace_recorder.MonitorUrl( | 357 loading_trace = trace_recorder.MonitorUrl( |
| 323 connection, url, | 358 connection, url, |
| 324 clear_cache=clear_cache, | 359 clear_cache=clear_cache, |
| 325 categories=pull_sandwich_metrics.CATEGORIES) | 360 categories=pull_sandwich_metrics.CATEGORIES, |
| 361 timeout=_DEVTOOLS_TIMEOUT) |
| 362 loading_trace.metadata.update(additional_metadata) |
| 326 if trace_id != None: | 363 if trace_id != None: |
| 327 loading_trace_path = os.path.join( | 364 loading_trace_path = os.path.join( |
| 328 args.output, str(trace_id), 'trace.json') | 365 args.output, str(trace_id), 'trace.json') |
| 329 os.makedirs(os.path.dirname(loading_trace_path)) | 366 os.makedirs(os.path.dirname(loading_trace_path)) |
| 330 loading_trace.ToJsonFile(loading_trace_path) | 367 loading_trace.ToJsonFile(loading_trace_path) |
| 331 | 368 |
| 332 for _ in xrange(args.repeat): | 369 for _ in xrange(args.repeat): |
| 333 for url in job_urls: | 370 for url in job_urls: |
| 334 clear_cache = False | 371 clear_cache = False |
| 335 if args.cache_op == 'clear': | 372 if args.cache_op == 'clear': |
| (...skipping 22 matching lines...) Expand all Loading... |
| 358 cache_directory_path = _PullBrowserCache(device) | 395 cache_directory_path = _PullBrowserCache(device) |
| 359 _ZipDirectoryContent(cache_directory_path, local_cache_archive_path) | 396 _ZipDirectoryContent(cache_directory_path, local_cache_archive_path) |
| 360 shutil.rmtree(cache_directory_path) | 397 shutil.rmtree(cache_directory_path) |
| 361 | 398 |
| 362 with open(os.path.join(args.output, 'run_infos.json'), 'w') as file_output: | 399 with open(os.path.join(args.output, 'run_infos.json'), 'w') as file_output: |
| 363 json.dump(run_infos, file_output, indent=2) | 400 json.dump(run_infos, file_output, indent=2) |
| 364 | 401 |
| 365 | 402 |
| 366 if __name__ == '__main__': | 403 if __name__ == '__main__': |
| 367 sys.exit(main()) | 404 sys.exit(main()) |
| OLD | NEW |