blob: b0b4c3acddcae3dfd8dc9c285b8c23ca379cebcb [file] [log] [blame]
Han Shen0d398632016-02-01 16:18:19 -08001# Copyright (c) 2013~2015 The Chromium OS Authors. All rights reserved.
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Rahul Chaudhrye57523a2016-01-15 14:30:14 -08004"""SuiteRunner defines the interface from crosperf to test script."""
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -07005
Rahul Chaudhrycbc5a262015-12-30 17:05:14 -08006from __future__ import print_function
7
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -07008import os
9import time
cmticee5a746f2013-11-25 14:57:10 -050010import shlex
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070011
Han Shen0d398632016-02-01 16:18:19 -080012from cros_utils import command_executer
Caroline Tice7057cf62015-12-10 12:09:40 -080013import test_flag
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070014
Caroline Tice92774192013-09-10 16:29:18 -070015TEST_THAT_PATH = '/usr/bin/test_that'
16CHROME_MOUNT_DIR = '/tmp/chrome_root'
17
Luis Lozanof2a3ef42015-12-15 13:49:30 -080018
19def GetProfilerArgs(profiler_args):
cmticee5a746f2013-11-25 14:57:10 -050020 # Remove "--" from in front of profiler args.
21 args_list = shlex.split(profiler_args)
22 new_list = []
23 for arg in args_list:
24 if arg[0:2] == '--':
25 arg = arg[2:]
26 new_list.append(arg)
27 args_list = new_list
28
29 # Remove "perf_options=" from middle of profiler args.
30 new_list = []
31 for arg in args_list:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080032 idx = arg.find('perf_options=')
cmticee5a746f2013-11-25 14:57:10 -050033 if idx != -1:
34 prefix = arg[0:idx]
Luis Lozanof2a3ef42015-12-15 13:49:30 -080035 suffix = arg[idx + len('perf_options=') + 1:-1]
cmticee5a746f2013-11-25 14:57:10 -050036 new_arg = prefix + "'" + suffix + "'"
37 new_list.append(new_arg)
38 else:
39 new_list.append(arg)
40 args_list = new_list
41
Luis Lozanof2a3ef42015-12-15 13:49:30 -080042 return ' '.join(args_list)
Caroline Tice92774192013-09-10 16:29:18 -070043
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070044
45class SuiteRunner(object):
Rahul Chaudhry3ebd0612015-12-30 18:16:07 -080046 """This defines the interface from crosperf to test script."""
Caroline Tice92774192013-09-10 16:29:18 -070047
Luis Lozanof2a3ef42015-12-15 13:49:30 -080048 def __init__(self,
49 logger_to_use=None,
50 log_level='verbose',
51 cmd_exec=None,
cmtice4f0309d2014-06-15 13:36:05 -070052 cmd_term=None):
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070053 self._logger = logger_to_use
cmtice13909242014-03-11 13:38:07 -070054 self.log_level = log_level
Luis Lozanof2a3ef42015-12-15 13:49:30 -080055 self._ce = cmd_exec or command_executer.GetCommandExecuter(
56 self._logger,
57 log_level=self.log_level)
cmtice4f0309d2014-06-15 13:36:05 -070058 self._ct = cmd_term or command_executer.CommandTerminator()
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070059
cmticee5a746f2013-11-25 14:57:10 -050060 def Run(self, machine, label, benchmark, test_args, profiler_args):
Luis Lozanodf762222015-05-19 12:22:37 -070061 for i in range(0, benchmark.retries + 1):
62 self.PinGovernorExecutionFrequencies(machine, label.chromeos_root)
Luis Lozanof2a3ef42015-12-15 13:49:30 -080063 if benchmark.suite == 'telemetry':
Luis Lozanodf762222015-05-19 12:22:37 -070064 ret_tup = self.Telemetry_Run(machine, label, benchmark, profiler_args)
Luis Lozanof2a3ef42015-12-15 13:49:30 -080065 elif benchmark.suite == 'telemetry_Crosperf':
Luis Lozanodf762222015-05-19 12:22:37 -070066 ret_tup = self.Telemetry_Crosperf_Run(machine, label, benchmark,
67 test_args, profiler_args)
68 else:
69 ret_tup = self.Test_That_Run(machine, label, benchmark, test_args,
70 profiler_args)
71 if ret_tup[0] != 0:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080072 self._logger.LogOutput('benchmark %s failed. Retries left: %s' %
73 (benchmark.name, benchmark.retries - i))
Luis Lozanodf762222015-05-19 12:22:37 -070074 elif i > 0:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080075 self._logger.LogOutput('benchmark %s succeded after %s retries' %
76 (benchmark.name, i))
Luis Lozanodf762222015-05-19 12:22:37 -070077 break
78 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080079 self._logger.LogOutput('benchmark %s succeded on first try' %
80 benchmark.name)
Luis Lozanodf762222015-05-19 12:22:37 -070081 break
82 return ret_tup
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070083
Luis Lozano53c88e92013-10-08 15:15:48 -070084 def GetHighestStaticFrequency(self, machine_name, chromeos_root):
Rahul Chaudhry3ebd0612015-12-30 18:16:07 -080085 """Gets the highest static frequency for the specified machine."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -080086 get_avail_freqs = ('cd /sys/devices/system/cpu/cpu0/cpufreq/; '
87 'if [[ -e scaling_available_frequencies ]]; then '
88 ' cat scaling_available_frequencies; '
89 'else '
90 ' cat scaling_max_freq ; '
91 'fi')
Luis Lozano036c9232015-12-10 10:47:01 -080092 ret, freqs_str, _ = self._ce.CrosRunCommandWOutput(
Luis Lozanof2a3ef42015-12-15 13:49:30 -080093 get_avail_freqs,
94 machine=machine_name,
95 chromeos_root=chromeos_root)
96 self._logger.LogFatalIf(ret, 'Could not get available frequencies '
97 'from machine: %s' % machine_name)
Luis Lozano53c88e92013-10-08 15:15:48 -070098 freqs = freqs_str.split()
Luis Lozanod0b46122015-12-07 15:09:33 -080099 # We need to make sure that the frequencies are sorted in decreasing
100 # order
101 freqs.sort(key=int, reverse=True)
102
Han Shenfd0b1782014-02-12 15:13:01 -0800103 ## When there is no scaling_available_frequencies file,
104 ## we have only 1 choice.
105 if len(freqs) == 1:
106 return freqs[0]
Luis Lozano53c88e92013-10-08 15:15:48 -0700107 # The dynamic frequency ends with a "1000". So, ignore it if found.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800108 if freqs[0].endswith('1000'):
Luis Lozano53c88e92013-10-08 15:15:48 -0700109 return freqs[1]
110 else:
111 return freqs[0]
112
113 def PinGovernorExecutionFrequencies(self, machine_name, chromeos_root):
Rahul Chaudhry3ebd0612015-12-30 18:16:07 -0800114 """Set min and max frequencies to max static frequency."""
Luis Lozano53c88e92013-10-08 15:15:48 -0700115 highest_freq = self.GetHighestStaticFrequency(machine_name, chromeos_root)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800116 BASH_FOR = 'for f in {list}; do {body}; done'
117 CPUFREQ_DIRS = '/sys/devices/system/cpu/cpu*/cpufreq/'
118 change_max_freq = BASH_FOR.format(list=CPUFREQ_DIRS + 'scaling_max_freq',
119 body='echo %s > $f' % highest_freq)
120 change_min_freq = BASH_FOR.format(list=CPUFREQ_DIRS + 'scaling_min_freq',
121 body='echo %s > $f' % highest_freq)
122 change_perf_gov = BASH_FOR.format(list=CPUFREQ_DIRS + 'scaling_governor',
123 body='echo performance > $f')
124 if self.log_level == 'average':
125 self._logger.LogOutput('Pinning governor execution frequencies for %s' %
126 machine_name)
127 ret = self._ce.CrosRunCommand(' && '.join((
128 'set -e ', change_max_freq, change_min_freq, change_perf_gov)),
Luis Lozano53c88e92013-10-08 15:15:48 -0700129 machine=machine_name,
130 chromeos_root=chromeos_root)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800131 self._logger.LogFatalIf(ret, 'Could not pin frequencies on machine: %s' %
132 machine_name)
Luis Lozano53c88e92013-10-08 15:15:48 -0700133
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700134 def RebootMachine(self, machine_name, chromeos_root):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800135 command = 'reboot && exit'
136 self._ce.CrosRunCommand(command,
137 machine=machine_name,
138 chromeos_root=chromeos_root)
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700139 time.sleep(60)
Luis Lozano53c88e92013-10-08 15:15:48 -0700140 # Whenever we reboot the machine, we need to restore the governor settings.
141 self.PinGovernorExecutionFrequencies(machine_name, chromeos_root)
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700142
cmticee5a746f2013-11-25 14:57:10 -0500143 def Test_That_Run(self, machine, label, benchmark, test_args, profiler_args):
Caroline Ticeb47bff42013-08-19 15:59:02 -0700144 """Run the test_that test.."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800145 options = ''
Caroline Ticeb47bff42013-08-19 15:59:02 -0700146 if label.board:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800147 options += ' --board=%s' % label.board
Caroline Ticeb47bff42013-08-19 15:59:02 -0700148 if test_args:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800149 options += ' %s' % test_args
cmticee5a746f2013-11-25 14:57:10 -0500150 if profiler_args:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800151 self._logger.LogFatal('test_that does not support profiler.')
152 command = 'rm -rf /usr/local/autotest/results/*'
153 self._ce.CrosRunCommand(command,
154 machine=machine,
Caroline Ticeb47bff42013-08-19 15:59:02 -0700155 chromeos_root=label.chromeos_root)
156
cmtice98a53692014-04-16 14:48:47 -0700157 # We do this because some tests leave the machine in weird states.
Luis Lozano53c88e92013-10-08 15:15:48 -0700158 # Rebooting between iterations has proven to help with this.
Caroline Ticeb47bff42013-08-19 15:59:02 -0700159 self.RebootMachine(machine, label.chromeos_root)
160
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800161 command = (
162 ('%s --autotest_dir ~/trunk/src/third_party/autotest/files --fast '
163 '%s %s %s') % (TEST_THAT_PATH, options, machine, benchmark.test_name))
164 if self.log_level != 'verbose':
165 self._logger.LogOutput('Running test.')
166 self._logger.LogOutput('CMD: %s' % command)
Luis Lozano45b53c52015-09-30 11:36:27 -0700167 # Use --no-ns-pid so that cros_sdk does not create a different
168 # process namespace and we can kill process created easily by
169 # their process group.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800170 return self._ce.ChrootRunCommandWOutput(label.chromeos_root,
171 command,
172 command_terminator=self._ct,
173 cros_sdk_options='--no-ns-pid')
Caroline Ticeb47bff42013-08-19 15:59:02 -0700174
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800175 def RemoveTelemetryTempFile(self, machine, chromeos_root):
176 filename = 'telemetry@%s' % machine
177 fullname = os.path.join(chromeos_root, 'chroot', 'tmp', filename)
cmtice146058f2015-07-24 14:04:12 -0700178 if os.path.exists(fullname):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800179 os.remove(fullname)
Caroline Tice92774192013-09-10 16:29:18 -0700180
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800181 def Telemetry_Crosperf_Run(self, machine, label, benchmark, test_args,
182 profiler_args):
Caroline Tice92774192013-09-10 16:29:18 -0700183 if not os.path.isdir(label.chrome_src):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800184 self._logger.LogFatal('Cannot find chrome src dir to'
185 ' run telemetry: %s' % label.chrome_src)
Caroline Tice92774192013-09-10 16:29:18 -0700186
cmtice146058f2015-07-24 14:04:12 -0700187 # Check for and remove temporary file that may have been left by
188 # previous telemetry runs (and which might prevent this run from
189 # working).
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800190 self.RemoveTelemetryTempFile(machine, label.chromeos_root)
cmtice146058f2015-07-24 14:04:12 -0700191
Luis Lozano004bccb2015-03-20 18:19:58 -0700192 # For telemetry runs, we can use the autotest copy from the source
193 # location. No need to have one under /build/<board>.
194 autotest_dir_arg = '--autotest_dir ~/trunk/src/third_party/autotest/files'
195
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800196 profiler_args = GetProfilerArgs(profiler_args)
197 fast_arg = ''
Luis Lozano5d7e21d2015-03-20 17:57:36 -0700198 if not profiler_args:
199 # --fast works unless we are doing profiling (autotest limitation).
200 # --fast avoids unnecessary copies of syslogs.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800201 fast_arg = '--fast'
202 args_string = ''
cmticee5a746f2013-11-25 14:57:10 -0500203 if test_args:
204 # Strip double quotes off args (so we can wrap them in single
205 # quotes, to pass through to Telemetry).
206 if test_args[0] == '"' and test_args[-1] == '"':
207 test_args = test_args[1:-1]
208 args_string = "test_args='%s'" % test_args
Luis Lozano004bccb2015-03-20 18:19:58 -0700209
Ting-Yuan Huangbc2d3d12015-07-02 13:09:03 +0800210 cmd = ('{} {} {} --board={} --args="{} run_local={} test={} '
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800211 '{}" {} telemetry_Crosperf'.format(
212 TEST_THAT_PATH, autotest_dir_arg, fast_arg, label.board,
213 args_string, benchmark.run_local, benchmark.test_name,
214 profiler_args, machine))
Luis Lozano5d7e21d2015-03-20 17:57:36 -0700215
Luis Lozano45b53c52015-09-30 11:36:27 -0700216 # Use --no-ns-pid so that cros_sdk does not create a different
217 # process namespace and we can kill process created easily by their
218 # process group.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800219 chrome_root_options = ('--no-ns-pid '
220 '--chrome_root={} --chrome_root_mount={} '
Luis Lozano45b53c52015-09-30 11:36:27 -0700221 "FEATURES=\"-usersandbox\" "
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800222 'CHROME_ROOT={}'.format(label.chrome_src,
223 CHROME_MOUNT_DIR,
224 CHROME_MOUNT_DIR))
225 if self.log_level != 'verbose':
226 self._logger.LogOutput('Running test.')
227 self._logger.LogOutput('CMD: %s' % cmd)
Luis Lozano036c9232015-12-10 10:47:01 -0800228 return self._ce.ChrootRunCommandWOutput(
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800229 label.chromeos_root,
230 cmd,
231 command_terminator=self._ct,
Luis Lozano036c9232015-12-10 10:47:01 -0800232 cros_sdk_options=chrome_root_options)
Caroline Tice92774192013-09-10 16:29:18 -0700233
cmtice226e3e02014-04-27 22:28:42 -0700234 def Telemetry_Run(self, machine, label, benchmark, profiler_args):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800235 telemetry_run_path = ''
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700236 if not os.path.isdir(label.chrome_src):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800237 self._logger.LogFatal('Cannot find chrome src dir to' ' run telemetry.')
cmtice98a53692014-04-16 14:48:47 -0700238 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800239 telemetry_run_path = os.path.join(label.chrome_src, 'src/tools/perf')
cmtice98a53692014-04-16 14:48:47 -0700240 if not os.path.exists(telemetry_run_path):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800241 self._logger.LogFatal('Cannot find %s directory.' % telemetry_run_path)
cmtice98a53692014-04-16 14:48:47 -0700242
cmtice226e3e02014-04-27 22:28:42 -0700243 if profiler_args:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800244 self._logger.LogFatal('Telemetry does not support the perf profiler.')
cmtice226e3e02014-04-27 22:28:42 -0700245
cmtice146058f2015-07-24 14:04:12 -0700246 # Check for and remove temporary file that may have been left by
247 # previous telemetry runs (and which might prevent this run from
248 # working).
Caroline Tice7057cf62015-12-10 12:09:40 -0800249 if not test_flag.GetTestMode():
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800250 self.RemoveTelemetryTempFile(machine, label.chromeos_root)
cmtice146058f2015-07-24 14:04:12 -0700251
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800252 rsa_key = os.path.join(
253 label.chromeos_root,
254 'src/scripts/mod_for_test_scripts/ssh_keys/testing_rsa')
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700255
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800256 cmd = ('cd {0} && '
257 './run_measurement '
258 '--browser=cros-chrome '
259 '--output-format=csv '
260 '--remote={1} '
261 '--identity {2} '
262 '{3} {4}'.format(telemetry_run_path, machine, rsa_key,
263 benchmark.test_name, benchmark.test_args))
264 if self.log_level != 'verbose':
265 self._logger.LogOutput('Running test.')
266 self._logger.LogOutput('CMD: %s' % cmd)
Luis Lozano036c9232015-12-10 10:47:01 -0800267 return self._ce.RunCommandWOutput(cmd, print_to_console=False)
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700268
Han Shen0d398632016-02-01 16:18:19 -0800269 def CommandTerminator(self):
270 return self._ct
271
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700272 def Terminate(self):
273 self._ct.Terminate()
274
275
276class MockSuiteRunner(object):
Rahul Chaudhrye7c6fbf2016-01-15 15:16:47 -0800277 """Mock suite runner for test."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800278
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700279 def __init__(self):
Caroline Tice92774192013-09-10 16:29:18 -0700280 self._true = True
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700281
Caroline Tice92774192013-09-10 16:29:18 -0700282 def Run(self, *_args):
283 if self._true:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800284 return [0, '', '']
Caroline Tice92774192013-09-10 16:29:18 -0700285 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800286 return [0, '', '']