1# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5""" 6Run a pre-defined set of pages on the DUT for Chrome profile collection. 7 8The purpose of this test is to exercise chrome with a meaningful set 9of pages while a profile of Chrome is captured. It also aims at using 10the minimum set of functionality from Telemetry since Telemetry is not 11very stable on ChromeOS at this point. 12 13This test is designed to be called from the telemetry_AFDOGenerate 14server test. The server test will start the "perf" profiling tool on 15the DUT before starting this test. It will also capture the chrome 16profile and upload it to Google Storage to be used for an optimized 17build of Chrome. 18""" 19 20import logging 21import os 22import sys 23import time 24import traceback 25 26from autotest_lib.client.common_lib.cros import chrome 27from autotest_lib.client.bin import test 28from autotest_lib.client.cros import httpd 29 30# List of page cycler pages to use for Chrome profiling 31PAGE_CYCLER_BENCHMARKS = [ 32 'alexa_us', 33 'bloat', 34 'dhtml', 35 'dom', 36 'intl1', 37 'intl2', 38 'morejs', 39 'morejsnp', 40 'moz', 41 'moz2' ] 42 43HTTP_PORT = 8000 44FILE_URL_PREFIX = 'http://localhost:%d/test_src/' % HTTP_PORT 45 46class telemetry_AFDOGenerateClient(test.test): 47 """ 48 Run a set of pre-defined set of pages to exercise Chrome so that 49 we can capture a Chrome profile. 50 """ 51 version = 1 52 53 54 def initialize(self): 55 """Setup required DEPS and start the http listener.""" 56 dep = 'page_cycler_dep' 57 dep_dir = os.path.join(self.autodir, 'deps', dep) 58 self.job.install_pkg(dep, 'dep', dep_dir) 59 self.listener = httpd.HTTPListener(HTTP_PORT, docroot=dep_dir) 60 self.listener.run() 61 62 63 def cleanup(self): 64 """Stop the active http listener.""" 65 self.listener.stop() 66 67 68 def run_once(self): 69 """Display predetermined set of pages so that we can profile Chrome.""" 70 with chrome.Chrome() as cr: 71 for benchmark in PAGE_CYCLER_BENCHMARKS: 72 self._try_page_cycler(cr, benchmark) 73 74 def _try_page_cycler(self, cr, benchmark): 75 """Try executing a page cycler and recover if browser dies. 76 77 Navigates to the specified page_cycler, checks if the browser 78 died while executing it and waits until browser recovers. 79 80 @param cr: instance of chrome.Chrome class to control chrome. 81 @param benchmark: page_cycler page to display. 82 """ 83 if cr.did_browser_crash( 84 lambda: self._navigate_page_cycler(cr, benchmark)): 85 logging.info('Browser died while navigating %s', benchmark) 86 logging.info('Trying to continue...') 87 cr.wait_for_browser_to_come_up() 88 89 90 def _navigate_page_cycler(self, cr, benchmark): 91 """Navigate to a specific page_cycler page. 92 93 Navigates to the specified page_cycler and waits for the value 94 of the __pc_done cookie to indicate it is done. 95 96 @param cr: instance of chrome.Chrome class to control chrome. 97 @param benchmark: page_cycler page to display. 98 """ 99 PC_START_PAGE = 'data/page_cycler/%s/start.html?auto=1' 100 PC_DONE_EXP = 'window.document.cookie.indexOf("__pc_done=1") >= 0' 101 tab = cr.browser.tabs.New() 102 try: 103 tab.Activate() 104 logging.info('Navigating to page cycler %s', benchmark) 105 start_time = time.time() 106 benchmark_start_page = PC_START_PAGE % benchmark 107 tab.Navigate(FILE_URL_PREFIX + benchmark_start_page) 108 tab.WaitForDocumentReadyStateToBeComplete(timeout=180) 109 tab.WaitForJavaScriptCondition(PC_DONE_EXP, timeout=600) 110 tab.Close() 111 end_time = time.time() 112 logging.info('Completed page cycler %s in %f seconds', 113 benchmark, end_time - start_time) 114 except Exception as unk_exc: 115 end_time = time.time() 116 logging.info('After navigating %s for %f seconds got exception %s', 117 benchmark, end_time - start_time, str(unk_exc)) 118 traceback.print_exc(file=sys.stdout) 119 raise 120