blob: dca735c8b34be8bd7e242609e53432f6d137392d [file] [log] [blame]
Simran Basi833814b2013-01-29 13:13:43 -08001# 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
Kuo-Hsin Yang4a006172018-04-25 14:44:55 +08005import json
Simran Basi833814b2013-01-29 13:13:43 -08006import logging
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +08007import numbers
8import numpy
Simran Basi833814b2013-01-29 13:13:43 -08009import os
Simran Basi833814b2013-01-29 13:13:43 -080010import StringIO
11
Simran Basi833814b2013-01-29 13:13:43 -080012from autotest_lib.client.common_lib import error, utils
13from autotest_lib.client.common_lib.cros import dev_server
14
15
Dave Tu6a404e62013-11-05 15:54:48 -080016TELEMETRY_RUN_BENCHMARKS_SCRIPT = 'tools/perf/run_benchmark'
Ilja H. Friedel086bc3f2014-02-27 22:17:55 -080017TELEMETRY_RUN_TESTS_SCRIPT = 'tools/telemetry/run_tests'
Gurchetan Singhfaf75e92017-04-17 18:09:44 -070018TELEMETRY_RUN_GPU_TESTS_SCRIPT = 'content/test/gpu/run_gpu_integration_test.py'
Mao Huangc9642d72017-09-28 16:50:02 +080019TELEMETRY_TIMEOUT_MINS = 150
Simran Basi833814b2013-01-29 13:13:43 -080020
Ting-Yuan Huange5b19132016-03-22 13:02:41 +080021DUT_CHROME_ROOT = '/usr/local/telemetry/src'
22
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +080023CHART_JSON_RESULT = 'results-chart.json'
24HISTOGRAM_SET_RESULT = 'histograms.json'
25
Simran Basi833814b2013-01-29 13:13:43 -080026# Result Statuses
27SUCCESS_STATUS = 'SUCCESS'
28WARNING_STATUS = 'WARNING'
29FAILED_STATUS = 'FAILED'
30
Kuo-Hsin Yang07da7b62018-08-08 16:56:06 +080031# A list of telemetry tests that cannot run on dut.
Kuo-Hsin Yange0915472018-09-10 10:36:16 +080032ON_DUT_BLACKLIST = [
Kuo-Hsin Yang120c2042019-06-21 17:09:32 +080033 'cros_ui_smoothness', # crbug/976839
Kuo-Hsin Yange0915472018-09-10 10:36:16 +080034 'loading.desktop', # crbug/882299
35 'rendering.desktop', # crbug/882291
36 'system_health.memory_desktop', # crbug/874386
37]
Simran Basi833814b2013-01-29 13:13:43 -080038
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +080039# A list of telemetry tests that output histograms.
40HISTOGRAMS_WHITELIST = [
41 'rendering.desktop',
42 'speedometer2',
43]
44
Simran Basi833814b2013-01-29 13:13:43 -080045class TelemetryResult(object):
46 """Class to represent the results of a telemetry run.
47
48 This class represents the results of a telemetry run, whether it ran
49 successful, failed or had warnings.
50 """
51
52
53 def __init__(self, exit_code=0, stdout='', stderr=''):
54 """Initializes this TelemetryResultObject instance.
55
56 @param status: Status of the telemtry run.
57 @param stdout: Stdout of the telemetry run.
58 @param stderr: Stderr of the telemetry run.
59 """
60 if exit_code == 0:
61 self.status = SUCCESS_STATUS
62 else:
63 self.status = FAILED_STATUS
64
Simran Basi833814b2013-01-29 13:13:43 -080065 self._stdout = stdout
66 self._stderr = stderr
67 self.output = '\n'.join([stdout, stderr])
68
69
Simran Basi833814b2013-01-29 13:13:43 -080070class TelemetryRunner(object):
71 """Class responsible for telemetry for a given build.
72
73 This class will extract and install telemetry on the devserver and is
74 responsible for executing the telemetry benchmarks and returning their
75 output to the caller.
76 """
77
Ting-Yuan Huang85dcde82016-04-08 17:41:32 +080078 def __init__(self, host, local=False, telemetry_on_dut=True):
Simran Basi833814b2013-01-29 13:13:43 -080079 """Initializes this telemetry runner instance.
80
81 If telemetry is not installed for this build, it will be.
Luis Lozano23ae3192013-11-08 16:22:46 -080082
Ting-Yuan Huange5b19132016-03-22 13:02:41 +080083 Basically, the following commands on the local pc on which test_that
84 will be executed, depending on the 4 possible combinations of
85 local x telemetry_on_dut:
86
87 local=True, telemetry_on_dut=False:
88 run_benchmark --browser=cros-chrome --remote=[dut] [test]
89
90 local=True, telemetry_on_dut=True:
91 ssh [dut] run_benchmark --browser=system [test]
92
93 local=False, telemetry_on_dut=False:
94 ssh [devserver] run_benchmark --browser=cros-chrome --remote=[dut] [test]
95
96 local=False, telemetry_on_dut=True:
97 ssh [devserver] ssh [dut] run_benchmark --browser=system [test]
98
Luis Lozano23ae3192013-11-08 16:22:46 -080099 @param host: Host where the test will be run.
100 @param local: If set, no devserver will be used, test will be run
101 locally.
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800102 If not set, "ssh [devserver] " will be appended to test
103 commands.
104 @param telemetry_on_dut: If set, telemetry itself (the test harness)
105 will run on dut.
106 It decides browser=[system|cros-chrome]
Simran Basi833814b2013-01-29 13:13:43 -0800107 """
108 self._host = host
Ilja H. Friedelc7bf3102014-05-13 17:31:25 -0700109 self._devserver = None
110 self._telemetry_path = None
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800111 self._telemetry_on_dut = telemetry_on_dut
Luis Lozano23ae3192013-11-08 16:22:46 -0800112 # TODO (llozano crbug.com/324964). Remove conditional code.
113 # Use a class hierarchy instead.
114 if local:
115 self._setup_local_telemetry()
116 else:
117 self._setup_devserver_telemetry()
118
119 logging.debug('Telemetry Path: %s', self._telemetry_path)
120
121
122 def _setup_devserver_telemetry(self):
123 """Setup Telemetry to use the devserver."""
124 logging.debug('Setting up telemetry for devserver testing')
Simran Basi833814b2013-01-29 13:13:43 -0800125 logging.debug('Grabbing build from AFE.')
Prathmesh Prabhucfff58a2017-02-06 10:07:43 -0800126 info = self._host.host_info_store.get()
127 if not info.build:
Simran Basi833814b2013-01-29 13:13:43 -0800128 logging.error('Unable to locate build label for host: %s.',
Dean Liaoe3e75f62017-11-14 10:36:43 +0800129 self._host.host_port)
Simran Basi833814b2013-01-29 13:13:43 -0800130 raise error.AutotestError('Failed to grab build for host %s.' %
Dean Liaoe3e75f62017-11-14 10:36:43 +0800131 self._host.host_port)
Simran Basi833814b2013-01-29 13:13:43 -0800132
Prathmesh Prabhucfff58a2017-02-06 10:07:43 -0800133 logging.debug('Setting up telemetry for build: %s', info.build)
Simran Basi833814b2013-01-29 13:13:43 -0800134
Prathmesh Prabhucfff58a2017-02-06 10:07:43 -0800135 self._devserver = dev_server.ImageServer.resolve(
136 info.build, hostname=self._host.hostname)
137 self._devserver.stage_artifacts(info.build, ['autotest_packages'])
138 self._telemetry_path = self._devserver.setup_telemetry(build=info.build)
Luis Lozano23ae3192013-11-08 16:22:46 -0800139
140
141 def _setup_local_telemetry(self):
142 """Setup Telemetry to use local path to its sources.
143
144 First look for chrome source root, either externally mounted, or inside
145 the chroot. Prefer chrome-src-internal source tree to chrome-src.
146 """
147 TELEMETRY_DIR = 'src'
148 CHROME_LOCAL_SRC = '/var/cache/chromeos-cache/distfiles/target/'
Josh Triplett05208c92014-07-17 13:21:29 -0700149 CHROME_EXTERNAL_SRC = os.path.expanduser('~/chrome_root/')
Luis Lozano23ae3192013-11-08 16:22:46 -0800150
151 logging.debug('Setting up telemetry for local testing')
152
153 sources_list = ('chrome-src-internal', 'chrome-src')
Josh Triplett05208c92014-07-17 13:21:29 -0700154 dir_list = [CHROME_EXTERNAL_SRC]
Luis Lozano23ae3192013-11-08 16:22:46 -0800155 dir_list.extend(
156 [os.path.join(CHROME_LOCAL_SRC, x) for x in sources_list])
157 if 'CHROME_ROOT' in os.environ:
158 dir_list.insert(0, os.environ['CHROME_ROOT'])
159
160 telemetry_src = ''
161 for dir in dir_list:
162 if os.path.exists(dir):
163 telemetry_src = os.path.join(dir, TELEMETRY_DIR)
164 break
165 else:
166 raise error.TestError('Telemetry source directory not found.')
167
168 self._devserver = None
169 self._telemetry_path = telemetry_src
170
171
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800172 def _get_telemetry_cmd(self, script, test_or_benchmark, output_format,
173 *args):
Luis Lozano23ae3192013-11-08 16:22:46 -0800174 """Build command to execute telemetry based on script and benchmark.
175
176 @param script: Telemetry script we want to run. For example:
177 [path_to_telemetry_src]/src/tools/telemetry/run_tests.
178 @param test_or_benchmark: Name of the test or benchmark we want to run,
179 with the page_set (if required) as part of
180 the string.
Luis Lozano814c7182015-09-08 11:20:47 -0700181 @param args: additional list of arguments to pass to the script.
182
Luis Lozano23ae3192013-11-08 16:22:46 -0800183 @returns Full telemetry command to execute the script.
184 """
185 telemetry_cmd = []
186 if self._devserver:
Allen Lia5cfb972016-12-27 17:17:22 -0800187 devserver_hostname = self._devserver.hostname
Luis Lozano23ae3192013-11-08 16:22:46 -0800188 telemetry_cmd.extend(['ssh', devserver_hostname])
189
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800190 if self._telemetry_on_dut:
191 telemetry_cmd.extend(
Dean Liaoe3e75f62017-11-14 10:36:43 +0800192 [self._host.ssh_command(alive_interval=900,
193 connection_attempts=4),
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800194 'python',
195 script,
196 '--verbose',
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800197 '--output-format=%s' % output_format,
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800198 '--output-dir=%s' % DUT_CHROME_ROOT,
199 '--browser=system'])
200 else:
201 telemetry_cmd.extend(
202 ['python',
203 script,
204 '--verbose',
205 '--browser=cros-chrome',
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800206 '--output-format=%s' % output_format,
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800207 '--output-dir=%s' % self._telemetry_path,
Dean Liaoe3e75f62017-11-14 10:36:43 +0800208 '--remote=%s' % self._host.host_port])
Luis Lozano814c7182015-09-08 11:20:47 -0700209 telemetry_cmd.extend(args)
210 telemetry_cmd.append(test_or_benchmark)
211
Keith Haddow1e5c7012016-03-09 16:05:37 -0800212 return ' '.join(telemetry_cmd)
213
214
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800215 def _scp_telemetry_results_cmd(self, perf_results_dir, output_format):
Keith Haddow1e5c7012016-03-09 16:05:37 -0800216 """Build command to copy the telemetry results from the devserver.
217
218 @param perf_results_dir: directory path where test output is to be
219 collected.
220 @returns SCP command to copy the results json to the specified directory.
221 """
Dean Liaoe3e75f62017-11-14 10:36:43 +0800222 if not perf_results_dir:
223 return ''
224
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800225 output_filename = CHART_JSON_RESULT
226 if output_format == 'histograms':
227 output_filename = HISTOGRAM_SET_RESULT
Dean Liaoe3e75f62017-11-14 10:36:43 +0800228 scp_cmd = ['scp']
229 if self._telemetry_on_dut:
230 scp_cmd.append(self._host.make_ssh_options(alive_interval=900,
231 connection_attempts=4))
232 if not self._host.is_default_port:
233 scp_cmd.append('-P %d' % self._host.port)
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800234 src = 'root@%s:%s/%s' % (self._host.hostname, DUT_CHROME_ROOT,
235 output_filename)
Dean Liaoe3e75f62017-11-14 10:36:43 +0800236 else:
237 devserver_hostname = ''
Ricky Liangd186f3e2016-03-15 16:50:55 +0800238 if self._devserver:
Allen Lia5cfb972016-12-27 17:17:22 -0800239 devserver_hostname = self._devserver.hostname + ':'
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800240 src = '%s%s/%s' % (devserver_hostname, self._telemetry_path,
241 output_filename)
Keith Haddow1e5c7012016-03-09 16:05:37 -0800242
Dean Liaoe3e75f62017-11-14 10:36:43 +0800243 scp_cmd.extend([src, perf_results_dir])
Keith Haddow1e5c7012016-03-09 16:05:37 -0800244 return ' '.join(scp_cmd)
245
246
247 def _run_cmd(self, cmd):
248 """Execute an command in a external shell and capture the output.
249
250 @param cmd: String of is a valid shell command.
251
252 @returns The standard out, standard error and the integer exit code of
253 the executed command.
254 """
255 logging.debug('Running: %s', cmd)
256
257 output = StringIO.StringIO()
258 error_output = StringIO.StringIO()
259 exit_code = 0
260 try:
261 result = utils.run(cmd, stdout_tee=output,
262 stderr_tee=error_output,
263 timeout=TELEMETRY_TIMEOUT_MINS*60)
264 exit_code = result.exit_status
265 except error.CmdError as e:
266 logging.debug('Error occurred executing.')
267 exit_code = e.result_obj.exit_status
268
269 stdout = output.getvalue()
270 stderr = error_output.getvalue()
271 logging.debug('Completed with exit code: %d.\nstdout:%s\n'
272 'stderr:%s', exit_code, stdout, stderr)
273 return stdout, stderr, exit_code
Simran Basi833814b2013-01-29 13:13:43 -0800274
275
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800276 def _run_telemetry(self, script, test_or_benchmark, output_format, *args):
Simran Basi833814b2013-01-29 13:13:43 -0800277 """Runs telemetry on a dut.
278
279 @param script: Telemetry script we want to run. For example:
Luis Lozano23ae3192013-11-08 16:22:46 -0800280 [path_to_telemetry_src]/src/tools/telemetry/run_tests.
Simran Basi833814b2013-01-29 13:13:43 -0800281 @param test_or_benchmark: Name of the test or benchmark we want to run,
282 with the page_set (if required) as part of the
283 string.
Luis Lozano814c7182015-09-08 11:20:47 -0700284 @param args: additional list of arguments to pass to the script.
Simran Basi833814b2013-01-29 13:13:43 -0800285
286 @returns A TelemetryResult Instance with the results of this telemetry
287 execution.
288 """
Simran Basi1dbfc132013-05-02 10:11:02 -0700289 # TODO (sbasi crbug.com/239933) add support for incognito mode.
Simran Basi833814b2013-01-29 13:13:43 -0800290
Luis Lozano814c7182015-09-08 11:20:47 -0700291 telemetry_cmd = self._get_telemetry_cmd(script,
292 test_or_benchmark,
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800293 output_format,
Luis Lozano814c7182015-09-08 11:20:47 -0700294 *args)
Keith Haddow1e5c7012016-03-09 16:05:37 -0800295 logging.debug('Running Telemetry: %s', telemetry_cmd)
Luis Lozano23ae3192013-11-08 16:22:46 -0800296
Keith Haddow1e5c7012016-03-09 16:05:37 -0800297 stdout, stderr, exit_code = self._run_cmd(telemetry_cmd)
Simran Basi833814b2013-01-29 13:13:43 -0800298
299 return TelemetryResult(exit_code=exit_code, stdout=stdout,
300 stderr=stderr)
301
302
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800303 def _run_scp(self, perf_results_dir, output_format):
Keith Haddow1e5c7012016-03-09 16:05:37 -0800304 """Runs telemetry on a dut.
305
306 @param perf_results_dir: The local directory that results are being
307 collected.
308 """
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800309 scp_cmd = self._scp_telemetry_results_cmd(perf_results_dir,
310 output_format)
Keith Haddow1e5c7012016-03-09 16:05:37 -0800311 logging.debug('Retrieving Results: %s', scp_cmd)
Dean Liaoe4773c72017-11-09 16:15:38 +0800312 _, _, exit_code = self._run_cmd(scp_cmd)
313 if exit_code != 0:
314 raise error.TestFail('Unable to retrieve results.')
Keith Haddow1e5c7012016-03-09 16:05:37 -0800315
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800316 if output_format == 'histograms':
317 # Converts to chart json format.
318 input_filename = os.path.join(perf_results_dir,
319 HISTOGRAM_SET_RESULT)
320 output_filename = os.path.join(perf_results_dir,
321 CHART_JSON_RESULT)
322 histograms = json.loads(open(input_filename).read())
323 chartjson = TelemetryRunner.convert_chart_json(histograms)
324 with open(output_filename, 'w') as fout:
325 fout.write(json.dumps(chartjson, indent=2))
Keith Haddow1e5c7012016-03-09 16:05:37 -0800326
Luis Lozano814c7182015-09-08 11:20:47 -0700327 def _run_test(self, script, test, *args):
Simran Basi1dbfc132013-05-02 10:11:02 -0700328 """Runs a telemetry test on a dut.
329
330 @param script: Which telemetry test script we want to run. Can be
331 telemetry's base test script or the Chrome OS specific
332 test script.
333 @param test: Telemetry test we want to run.
Luis Lozano814c7182015-09-08 11:20:47 -0700334 @param args: additional list of arguments to pass to the script.
Simran Basi1dbfc132013-05-02 10:11:02 -0700335
336 @returns A TelemetryResult Instance with the results of this telemetry
337 execution.
338 """
339 logging.debug('Running telemetry test: %s', test)
340 telemetry_script = os.path.join(self._telemetry_path, script)
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800341 result = self._run_telemetry(telemetry_script, test, 'chartjson', *args)
Simran Basi1dbfc132013-05-02 10:11:02 -0700342 if result.status is FAILED_STATUS:
Ilja H. Friedelc7bf3102014-05-13 17:31:25 -0700343 raise error.TestFail('Telemetry test %s failed.' % test)
Simran Basi1dbfc132013-05-02 10:11:02 -0700344 return result
345
346
Luis Lozano814c7182015-09-08 11:20:47 -0700347 def run_telemetry_test(self, test, *args):
Simran Basi833814b2013-01-29 13:13:43 -0800348 """Runs a telemetry test on a dut.
349
350 @param test: Telemetry test we want to run.
Luis Lozano814c7182015-09-08 11:20:47 -0700351 @param args: additional list of arguments to pass to the telemetry
352 execution script.
Simran Basi833814b2013-01-29 13:13:43 -0800353
354 @returns A TelemetryResult Instance with the results of this telemetry
355 execution.
356 """
Luis Lozano814c7182015-09-08 11:20:47 -0700357 return self._run_test(TELEMETRY_RUN_TESTS_SCRIPT, test, *args)
Simran Basi1dbfc132013-05-02 10:11:02 -0700358
359
Luis Lozano814c7182015-09-08 11:20:47 -0700360 def run_telemetry_benchmark(self, benchmark, perf_value_writer=None,
361 *args):
Simran Basi833814b2013-01-29 13:13:43 -0800362 """Runs a telemetry benchmark on a dut.
363
364 @param benchmark: Benchmark we want to run.
Fang Denge689e712013-11-13 18:27:06 -0800365 @param perf_value_writer: Should be an instance with the function
366 output_perf_value(), if None, no perf value
367 will be written. Typically this will be the
368 job object from an autotest test.
Luis Lozano814c7182015-09-08 11:20:47 -0700369 @param args: additional list of arguments to pass to the telemetry
370 execution script.
Simran Basi833814b2013-01-29 13:13:43 -0800371
372 @returns A TelemetryResult Instance with the results of this telemetry
373 execution.
374 """
Dave Tu6a404e62013-11-05 15:54:48 -0800375 logging.debug('Running telemetry benchmark: %s', benchmark)
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800376
Kuo-Hsin Yang07da7b62018-08-08 16:56:06 +0800377 if benchmark in ON_DUT_BLACKLIST:
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800378 self._telemetry_on_dut = False
379
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800380 output_format = 'chartjson'
381 if benchmark in HISTOGRAMS_WHITELIST:
382 output_format = 'histograms'
383
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800384 if self._telemetry_on_dut:
385 telemetry_script = os.path.join(DUT_CHROME_ROOT,
386 TELEMETRY_RUN_BENCHMARKS_SCRIPT)
387 self._ensure_deps(self._host, benchmark)
388 else:
389 telemetry_script = os.path.join(self._telemetry_path,
390 TELEMETRY_RUN_BENCHMARKS_SCRIPT)
391
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800392 result = self._run_telemetry(telemetry_script, benchmark,
393 output_format, *args)
Simran Basi833814b2013-01-29 13:13:43 -0800394
395 if result.status is WARNING_STATUS:
Dave Tu6a404e62013-11-05 15:54:48 -0800396 raise error.TestWarn('Telemetry Benchmark: %s'
397 ' exited with Warnings.' % benchmark)
Simran Basi833814b2013-01-29 13:13:43 -0800398 if result.status is FAILED_STATUS:
Dave Tu6a404e62013-11-05 15:54:48 -0800399 raise error.TestFail('Telemetry Benchmark: %s'
400 ' failed to run.' % benchmark)
Keith Haddow1e5c7012016-03-09 16:05:37 -0800401 if perf_value_writer:
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800402 self._run_scp(perf_value_writer.resultsdir, output_format)
Simran Basi833814b2013-01-29 13:13:43 -0800403 return result
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800404
Gurchetan Singhfaf75e92017-04-17 18:09:44 -0700405
406 def run_gpu_integration_test(self, test, *args):
407 """Runs a gpu test on a dut.
408
409 @param test: Gpu test we want to run.
410 @param args: additional list of arguments to pass to the telemetry
411 execution script.
412
Drew Davenport84395922018-09-10 10:42:37 -0600413 @returns A TelemetryResult instance with the results of this telemetry
414 execution.
Gurchetan Singhfaf75e92017-04-17 18:09:44 -0700415 """
416 script = os.path.join(DUT_CHROME_ROOT,
417 TELEMETRY_RUN_GPU_TESTS_SCRIPT)
418 cmd = []
419 if self._devserver:
420 devserver_hostname = self._devserver.hostname
421 cmd.extend(['ssh', devserver_hostname])
422
423 cmd.extend(
Dean Liaoe3e75f62017-11-14 10:36:43 +0800424 [self._host.ssh_command(alive_interval=900, connection_attempts=4),
425 'python', script])
Gurchetan Singhfaf75e92017-04-17 18:09:44 -0700426 cmd.extend(args)
427 cmd.append(test)
428 cmd = ' '.join(cmd)
429 stdout, stderr, exit_code = self._run_cmd(cmd)
430
Drew Davenport84395922018-09-10 10:42:37 -0600431 if exit_code:
432 raise error.TestFail('Gpu Integration Test: %s'
433 ' failed to run.' % test)
434
Gurchetan Singhfaf75e92017-04-17 18:09:44 -0700435 return TelemetryResult(exit_code=exit_code, stdout=stdout,
436 stderr=stderr)
437
438
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800439 def _ensure_deps(self, dut, test_name):
440 """
441 Ensure the dependencies are locally available on DUT.
442
443 @param dut: The autotest host object representing DUT.
444 @param test_name: Name of the telemetry test.
445 """
446 # Get DEPs using host's telemetry.
Kuo-Hsin Yang4a006172018-04-25 14:44:55 +0800447 # Example output, fetch_benchmark_deps.py --output-deps=deps octane:
448 # {'octane': ['tools/perf/page_sets/data/octane_002.wprgo']}
449 perf_path = os.path.join(self._telemetry_path, 'tools', 'perf')
450 deps_path = os.path.join(perf_path, 'fetch_benchmark_deps_result.json')
451 fetch_path = os.path.join(perf_path, 'fetch_benchmark_deps.py')
452 format_fetch = ('python %s --output-deps=%s %s')
453 command_fetch = format_fetch % (fetch_path, deps_path, test_name)
454 command_get = 'cat %s' % deps_path
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800455
456 if self._devserver:
457 devserver_hostname = self._devserver.url().split(
458 'http://')[1].split(':')[0]
Kuo-Hsin Yang4a006172018-04-25 14:44:55 +0800459 command_fetch = 'ssh %s %s' % (devserver_hostname, command_fetch)
460 command_get = 'ssh %s %s' % (devserver_hostname, command_get)
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800461
Kuo-Hsin Yang4a006172018-04-25 14:44:55 +0800462 logging.info('Getting DEPs: %s', command_fetch)
463 _, _, exit_code = self._run_cmd(command_fetch)
464 if exit_code != 0:
465 raise error.TestFail('Error occurred while fetching DEPs.')
466 stdout, _, exit_code = self._run_cmd(command_get)
467 if exit_code != 0:
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800468 raise error.TestFail('Error occurred while getting DEPs.')
469
470 # Download DEPs to DUT.
471 # send_file() relies on rsync over ssh. Couldn't be better.
Kuo-Hsin Yang4a006172018-04-25 14:44:55 +0800472 deps = json.loads(stdout)
473 for dep in deps[test_name]:
Ting-Yuan Huange5b19132016-03-22 13:02:41 +0800474 src = os.path.join(self._telemetry_path, dep)
475 dst = os.path.join(DUT_CHROME_ROOT, dep)
Ting-Yuan Huang8a2c7f72016-03-28 22:01:07 +0800476 if self._devserver:
477 logging.info('Copying: %s -> %s', src, dst)
Chung-yih Wangfd8eb242017-12-09 19:23:04 +0800478 rsync_cmd = utils.sh_escape('rsync %s %s %s:%s' %
479 (self._host.rsync_options(), src,
480 self._host.hostname, dst))
481 utils.run('ssh %s "%s"' % (devserver_hostname, rsync_cmd))
Ting-Yuan Huang8a2c7f72016-03-28 22:01:07 +0800482 else:
483 if not os.path.isfile(src):
484 raise error.TestFail('Error occurred while saving DEPs.')
485 logging.info('Copying: %s -> %s', src, dst)
486 dut.send_file(src, dst)
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800487
488 @staticmethod
489 def convert_chart_json(histogram_set):
490 """
491 Convert from histogram set to chart json format.
492
493 @param histogram_set: result in histogram set format.
494
495 @returns result in chart json format.
496 """
497 value_map = {}
498
499 # Gets generic set values.
500 for obj in histogram_set:
501 if 'type' in obj and obj['type'] == 'GenericSet':
502 value_map[obj['guid']] = obj['values']
503
504 # Mapping histogram set units to chart json units.
505 units_map = {'ms_smallerIsBetter': 'ms',
506 'unitless_biggerIsBetter': 'score'}
507
508 charts = {}
509 benchmark_name = ''
510 benchmark_desc = ''
511
512 # Checks the unit test for how this conversion works.
513 for obj in histogram_set:
514 if 'name' not in obj or 'sampleValues' not in obj:
515 continue
516 metric_name = obj['name']
517 diagnostics = obj['diagnostics']
518 story_name = value_map[diagnostics['stories']][0]
519 local_benchmark_name = value_map[diagnostics['benchmarks']][0]
520 if benchmark_name is '':
521 benchmark_name = local_benchmark_name
522 benchmark_desc = value_map[
523 diagnostics['benchmarkDescriptions']][0]
524 assert(benchmark_name == local_benchmark_name,
525 'There are more than 1 benchmark names in the result, '
526 'could not parse.')
527 unit = units_map.get(obj['unit'], '')
Kuo-Hsin Yange01ff602019-06-14 11:33:31 +0800528 improvement = 'up'
529 if obj['unit'].endswith('smallerIsBetter'):
530 improvement = 'down'
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800531 values = [x for x in obj['sampleValues']
532 if isinstance(x, numbers.Number)]
533 if metric_name not in charts:
534 charts[metric_name] = {}
535 charts[metric_name][story_name] = {
Kuo-Hsin Yange01ff602019-06-14 11:33:31 +0800536 'improvement_direction': improvement,
537 'name': metric_name,
538 'std': numpy.std(values),
539 'type': 'list_of_scalar_values',
540 'units': unit,
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800541 'values': values
542 }
543
544 # Adds summaries.
545 for metric_name in charts:
546 values = []
547 metric_content = charts[metric_name]
548 for story_name in metric_content:
549 story_content = metric_content[story_name]
550 values += story_content['values']
551 metric_type = story_content['type']
552 units = story_content['units']
Kuo-Hsin Yange01ff602019-06-14 11:33:31 +0800553 improvement = story_content['improvement_direction']
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800554 values.sort()
555 std = numpy.std(values)
556 metric_content['summary'] = {
Kuo-Hsin Yange01ff602019-06-14 11:33:31 +0800557 'improvement_direction': improvement,
558 'name': metric_name,
559 'std': std,
560 'type': metric_type,
561 'units': units,
562 'values': values
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800563 }
564
565 benchmark_metadata = {
Kuo-Hsin Yange01ff602019-06-14 11:33:31 +0800566 'description': benchmark_desc,
567 'name': benchmark_name,
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800568 'type': 'telemetry_benchmark'
569 }
Kuo-Hsin Yange01ff602019-06-14 11:33:31 +0800570 return {
571 'benchmark_description': benchmark_desc,
572 'benchmark_metadata': benchmark_metadata,
573 'benchmark_name': benchmark_name,
574 'charts': charts,
575 'format_version': 1.0
576 }
Kuo-Hsin Yang14d002b2019-06-06 13:18:04 +0800577