1 # Copyright (c) 2013 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 import logging 5 import os 6 import StringIO 7 8 import common 9 from autotest_lib.client.common_lib import error 10 from autotest_lib.server import test 11 from autotest_lib.server import utils 12 from autotest_lib.server.cros import telemetry_runner 13 14 15 TELEMETRY_TIMEOUT_MINS = 60 16 CHROME_SRC_ROOT = '/var/cache/chromeos-cache/distfiles/target/' 17 CLIENT_CHROME_ROOT = '/usr/local/telemetry/src' 18 RUN_BENCHMARK = 'tools/perf/run_benchmark' 19 20 21 def _find_chrome_root_dir(): 22 # Look for chrome source root, either externally mounted, or inside 23 # the chroot. Prefer chrome-src-internal source tree to chrome-src. 24 sources_list = ('chrome-src-internal', 'chrome-src') 25 26 dir_list = [os.path.join(CHROME_SRC_ROOT, x) for x in sources_list] 27 if 'CHROME_ROOT' in os.environ: 28 dir_list.insert(0, os.environ['CHROME_ROOT']) 29 30 for dir in dir_list: 31 if os.path.exists(dir): 32 chrome_root_dir = dir 33 break 34 else: 35 raise error.TestError('Chrome source directory not found.') 36 37 logging.info('Using Chrome source tree at %s', chrome_root_dir) 38 return os.path.join(chrome_root_dir, 'src') 39 40 41 def _ensure_deps(dut, test_name): 42 """ 43 Ensure the dependencies are locally available on DUT. 44 45 @param dut: The autotest host object representing DUT. 46 @param test_name: Name of the telemetry test. 47 """ 48 # Get DEPs using host's telemetry. 49 chrome_root_dir = _find_chrome_root_dir() 50 format_string = ('python %s/tools/perf/fetch_benchmark_deps.py %s') 51 command = format_string % (chrome_root_dir, test_name) 52 logging.info('Getting DEPs: %s', command) 53 stdout = StringIO.StringIO() 54 stderr = StringIO.StringIO() 55 try: 56 result = utils.run(command, stdout_tee=stdout, 57 stderr_tee=stderr) 58 except error.CmdError as e: 59 logging.debug('Error occurred getting DEPs: %s\n %s\n', 60 stdout.getvalue(), stderr.getvalue()) 61 raise error.TestFail('Error occurred while getting DEPs.') 62 63 # Download DEPs to DUT. 64 # send_file() relies on rsync over ssh. Couldn't be better. 65 stdout_str = stdout.getvalue() 66 stdout.close() 67 stderr.close() 68 for dep in stdout_str.split(): 69 src = os.path.join(chrome_root_dir, dep) 70 dst = os.path.join(CLIENT_CHROME_ROOT, dep) 71 if not os.path.isfile(src): 72 raise error.TestFail('Error occurred while saving DEPs.') 73 logging.info('Copying: %s -> %s', src, dst) 74 try: 75 dut.send_file(src, dst) 76 except: 77 raise error.TestFail('Error occurred while sending DEPs to dut.\n') 78 79 80 class telemetry_Crosperf(test.test): 81 """Run one or more telemetry benchmarks under the crosperf script.""" 82 version = 1 83 84 def run_once(self, args, client_ip='', dut=None): 85 """ 86 Run a single telemetry test. 87 88 @param args: A dictionary of the arguments that were passed 89 to this test. 90 @param client_ip: The ip address of the DUT 91 @param dut: The autotest host object representing DUT. 92 93 @returns A TelemetryResult instance with the results of this execution. 94 """ 95 test_name = args['test'] 96 test_args = '' 97 if 'test_args' in args: 98 test_args = args['test_args'] 99 100 # Decide whether the test will run locally or by a remote server. 101 if 'run_local' in args and args['run_local'].lower() == 'true': 102 # The telemetry scripts will run on DUT. 103 _ensure_deps(dut, test_name) 104 format_string = ('python %s --browser=system %s %s') 105 command = format_string % (os.path.join(CLIENT_CHROME_ROOT, 106 RUN_BENCHMARK), 107 test_args, test_name) 108 runner = dut 109 else: 110 # The telemetry scripts will run on server. 111 format_string = ('python %s --browser=cros-chrome --remote=%s ' 112 '%s %s') 113 command = format_string % (os.path.join(_find_chrome_root_dir(), 114 RUN_BENCHMARK), 115 client_ip, test_args, test_name) 116 runner = utils 117 118 # Run the test. 119 stdout = StringIO.StringIO() 120 stderr = StringIO.StringIO() 121 try: 122 logging.info('CMD: %s', command) 123 result = runner.run(command, stdout_tee=stdout, stderr_tee=stderr, 124 timeout=TELEMETRY_TIMEOUT_MINS*60) 125 exit_code = result.exit_status 126 except error.CmdError as e: 127 logging.debug('Error occurred executing telemetry.') 128 exit_code = e.result_obj.exit_status 129 raise error.TestFail('An error occurred while executing ' 130 'telemetry test.') 131 finally: 132 stdout_str = stdout.getvalue() 133 stderr_str = stderr.getvalue() 134 stdout.close() 135 stderr.close() 136 137 138 # Parse the result. 139 logging.debug('Telemetry completed with exit code: %d.' 140 '\nstdout:%s\nstderr:%s', exit_code, 141 stdout_str, stderr_str) 142 logging.info('Telemetry completed with exit code: %d.' 143 '\nstdout:%s\nstderr:%s', exit_code, 144 stdout_str, stderr_str) 145 146 result = telemetry_runner.TelemetryResult(exit_code=exit_code, 147 stdout=stdout_str, 148 stderr=stderr_str) 149 150 result.parse_benchmark_results() 151 for data in result.perf_data: 152 self.output_perf_value(description=data['trace'], 153 value=data['value'], 154 units=data['units'], 155 graph=data['graph']) 156 157 return result 158