blob: ae502bdeaa1b64aead10ef174314f8b091ca0f25 [file] [log] [blame]
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -07001# 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
Rahul Chaudhrycbc5a262015-12-30 17:05:14 -08005from __future__ import print_function
6
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -07007import os
8import time
cmticee5a746f2013-11-25 14:57:10 -05009import shlex
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070010
11from utils import command_executer
Caroline Tice7057cf62015-12-10 12:09:40 -080012import test_flag
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070013
Caroline Tice92774192013-09-10 16:29:18 -070014TEST_THAT_PATH = '/usr/bin/test_that'
15CHROME_MOUNT_DIR = '/tmp/chrome_root'
16
Luis Lozanof2a3ef42015-12-15 13:49:30 -080017
18def GetProfilerArgs(profiler_args):
cmticee5a746f2013-11-25 14:57:10 -050019 # Remove "--" from in front of profiler args.
20 args_list = shlex.split(profiler_args)
21 new_list = []
22 for arg in args_list:
23 if arg[0:2] == '--':
24 arg = arg[2:]
25 new_list.append(arg)
26 args_list = new_list
27
28 # Remove "perf_options=" from middle of profiler args.
29 new_list = []
30 for arg in args_list:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080031 idx = arg.find('perf_options=')
cmticee5a746f2013-11-25 14:57:10 -050032 if idx != -1:
33 prefix = arg[0:idx]
Luis Lozanof2a3ef42015-12-15 13:49:30 -080034 suffix = arg[idx + len('perf_options=') + 1:-1]
cmticee5a746f2013-11-25 14:57:10 -050035 new_arg = prefix + "'" + suffix + "'"
36 new_list.append(new_arg)
37 else:
38 new_list.append(arg)
39 args_list = new_list
40
Luis Lozanof2a3ef42015-12-15 13:49:30 -080041 return ' '.join(args_list)
Caroline Tice92774192013-09-10 16:29:18 -070042
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070043
44class SuiteRunner(object):
Rahul Chaudhry3ebd0612015-12-30 18:16:07 -080045 """This defines the interface from crosperf to test script."""
Caroline Tice92774192013-09-10 16:29:18 -070046
Luis Lozanof2a3ef42015-12-15 13:49:30 -080047 def __init__(self,
48 logger_to_use=None,
49 log_level='verbose',
50 cmd_exec=None,
cmtice4f0309d2014-06-15 13:36:05 -070051 cmd_term=None):
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070052 self._logger = logger_to_use
cmtice13909242014-03-11 13:38:07 -070053 self.log_level = log_level
Luis Lozanof2a3ef42015-12-15 13:49:30 -080054 self._ce = cmd_exec or command_executer.GetCommandExecuter(
55 self._logger,
56 log_level=self.log_level)
cmtice4f0309d2014-06-15 13:36:05 -070057 self._ct = cmd_term or command_executer.CommandTerminator()
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070058
cmticee5a746f2013-11-25 14:57:10 -050059 def Run(self, machine, label, benchmark, test_args, profiler_args):
Luis Lozanodf762222015-05-19 12:22:37 -070060 for i in range(0, benchmark.retries + 1):
61 self.PinGovernorExecutionFrequencies(machine, label.chromeos_root)
Luis Lozanof2a3ef42015-12-15 13:49:30 -080062 if benchmark.suite == 'telemetry':
Luis Lozanodf762222015-05-19 12:22:37 -070063 ret_tup = self.Telemetry_Run(machine, label, benchmark, profiler_args)
Luis Lozanof2a3ef42015-12-15 13:49:30 -080064 elif benchmark.suite == 'telemetry_Crosperf':
Luis Lozanodf762222015-05-19 12:22:37 -070065 ret_tup = self.Telemetry_Crosperf_Run(machine, label, benchmark,
66 test_args, profiler_args)
67 else:
68 ret_tup = self.Test_That_Run(machine, label, benchmark, test_args,
69 profiler_args)
70 if ret_tup[0] != 0:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080071 self._logger.LogOutput('benchmark %s failed. Retries left: %s' %
72 (benchmark.name, benchmark.retries - i))
Luis Lozanodf762222015-05-19 12:22:37 -070073 elif i > 0:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080074 self._logger.LogOutput('benchmark %s succeded after %s retries' %
75 (benchmark.name, i))
Luis Lozanodf762222015-05-19 12:22:37 -070076 break
77 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080078 self._logger.LogOutput('benchmark %s succeded on first try' %
79 benchmark.name)
Luis Lozanodf762222015-05-19 12:22:37 -070080 break
81 return ret_tup
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -070082
Luis Lozano53c88e92013-10-08 15:15:48 -070083 def GetHighestStaticFrequency(self, machine_name, chromeos_root):
Rahul Chaudhry3ebd0612015-12-30 18:16:07 -080084 """Gets the highest static frequency for the specified machine."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -080085 get_avail_freqs = ('cd /sys/devices/system/cpu/cpu0/cpufreq/; '
86 'if [[ -e scaling_available_frequencies ]]; then '
87 ' cat scaling_available_frequencies; '
88 'else '
89 ' cat scaling_max_freq ; '
90 'fi')
Luis Lozano036c9232015-12-10 10:47:01 -080091 ret, freqs_str, _ = self._ce.CrosRunCommandWOutput(
Luis Lozanof2a3ef42015-12-15 13:49:30 -080092 get_avail_freqs,
93 machine=machine_name,
94 chromeos_root=chromeos_root)
95 self._logger.LogFatalIf(ret, 'Could not get available frequencies '
96 'from machine: %s' % machine_name)
Luis Lozano53c88e92013-10-08 15:15:48 -070097 freqs = freqs_str.split()
Luis Lozanod0b46122015-12-07 15:09:33 -080098 # We need to make sure that the frequencies are sorted in decreasing
99 # order
100 freqs.sort(key=int, reverse=True)
101
Han Shenfd0b1782014-02-12 15:13:01 -0800102 ## When there is no scaling_available_frequencies file,
103 ## we have only 1 choice.
104 if len(freqs) == 1:
105 return freqs[0]
Luis Lozano53c88e92013-10-08 15:15:48 -0700106 # The dynamic frequency ends with a "1000". So, ignore it if found.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800107 if freqs[0].endswith('1000'):
Luis Lozano53c88e92013-10-08 15:15:48 -0700108 return freqs[1]
109 else:
110 return freqs[0]
111
112 def PinGovernorExecutionFrequencies(self, machine_name, chromeos_root):
Rahul Chaudhry3ebd0612015-12-30 18:16:07 -0800113 """Set min and max frequencies to max static frequency."""
Luis Lozano53c88e92013-10-08 15:15:48 -0700114 highest_freq = self.GetHighestStaticFrequency(machine_name, chromeos_root)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800115 BASH_FOR = 'for f in {list}; do {body}; done'
116 CPUFREQ_DIRS = '/sys/devices/system/cpu/cpu*/cpufreq/'
117 change_max_freq = BASH_FOR.format(list=CPUFREQ_DIRS + 'scaling_max_freq',
118 body='echo %s > $f' % highest_freq)
119 change_min_freq = BASH_FOR.format(list=CPUFREQ_DIRS + 'scaling_min_freq',
120 body='echo %s > $f' % highest_freq)
121 change_perf_gov = BASH_FOR.format(list=CPUFREQ_DIRS + 'scaling_governor',
122 body='echo performance > $f')
123 if self.log_level == 'average':
124 self._logger.LogOutput('Pinning governor execution frequencies for %s' %
125 machine_name)
126 ret = self._ce.CrosRunCommand(' && '.join((
127 'set -e ', change_max_freq, change_min_freq, change_perf_gov)),
Luis Lozano53c88e92013-10-08 15:15:48 -0700128 machine=machine_name,
129 chromeos_root=chromeos_root)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800130 self._logger.LogFatalIf(ret, 'Could not pin frequencies on machine: %s' %
131 machine_name)
Luis Lozano53c88e92013-10-08 15:15:48 -0700132
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700133 def RebootMachine(self, machine_name, chromeos_root):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800134 command = 'reboot && exit'
135 self._ce.CrosRunCommand(command,
136 machine=machine_name,
137 chromeos_root=chromeos_root)
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700138 time.sleep(60)
Luis Lozano53c88e92013-10-08 15:15:48 -0700139 # Whenever we reboot the machine, we need to restore the governor settings.
140 self.PinGovernorExecutionFrequencies(machine_name, chromeos_root)
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700141
cmticee5a746f2013-11-25 14:57:10 -0500142 def Test_That_Run(self, machine, label, benchmark, test_args, profiler_args):
Caroline Ticeb47bff42013-08-19 15:59:02 -0700143 """Run the test_that test.."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800144 options = ''
Caroline Ticeb47bff42013-08-19 15:59:02 -0700145 if label.board:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800146 options += ' --board=%s' % label.board
Caroline Ticeb47bff42013-08-19 15:59:02 -0700147 if test_args:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800148 options += ' %s' % test_args
cmticee5a746f2013-11-25 14:57:10 -0500149 if profiler_args:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800150 self._logger.LogFatal('test_that does not support profiler.')
151 command = 'rm -rf /usr/local/autotest/results/*'
152 self._ce.CrosRunCommand(command,
153 machine=machine,
Caroline Ticeb47bff42013-08-19 15:59:02 -0700154 chromeos_root=label.chromeos_root)
155
cmtice98a53692014-04-16 14:48:47 -0700156 # We do this because some tests leave the machine in weird states.
Luis Lozano53c88e92013-10-08 15:15:48 -0700157 # Rebooting between iterations has proven to help with this.
Caroline Ticeb47bff42013-08-19 15:59:02 -0700158 self.RebootMachine(machine, label.chromeos_root)
159
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800160 command = (
161 ('%s --autotest_dir ~/trunk/src/third_party/autotest/files --fast '
162 '%s %s %s') % (TEST_THAT_PATH, options, machine, benchmark.test_name))
163 if self.log_level != 'verbose':
164 self._logger.LogOutput('Running test.')
165 self._logger.LogOutput('CMD: %s' % command)
Luis Lozano45b53c52015-09-30 11:36:27 -0700166 # Use --no-ns-pid so that cros_sdk does not create a different
167 # process namespace and we can kill process created easily by
168 # their process group.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800169 return self._ce.ChrootRunCommandWOutput(label.chromeos_root,
170 command,
171 command_terminator=self._ct,
172 cros_sdk_options='--no-ns-pid')
Caroline Ticeb47bff42013-08-19 15:59:02 -0700173
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800174 def RemoveTelemetryTempFile(self, machine, chromeos_root):
175 filename = 'telemetry@%s' % machine
176 fullname = os.path.join(chromeos_root, 'chroot', 'tmp', filename)
cmtice146058f2015-07-24 14:04:12 -0700177 if os.path.exists(fullname):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800178 os.remove(fullname)
Caroline Tice92774192013-09-10 16:29:18 -0700179
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800180 def Telemetry_Crosperf_Run(self, machine, label, benchmark, test_args,
181 profiler_args):
Caroline Tice92774192013-09-10 16:29:18 -0700182 if not os.path.isdir(label.chrome_src):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800183 self._logger.LogFatal('Cannot find chrome src dir to'
184 ' run telemetry: %s' % label.chrome_src)
Caroline Tice92774192013-09-10 16:29:18 -0700185
cmtice146058f2015-07-24 14:04:12 -0700186 # Check for and remove temporary file that may have been left by
187 # previous telemetry runs (and which might prevent this run from
188 # working).
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800189 self.RemoveTelemetryTempFile(machine, label.chromeos_root)
cmtice146058f2015-07-24 14:04:12 -0700190
Luis Lozano004bccb2015-03-20 18:19:58 -0700191 # For telemetry runs, we can use the autotest copy from the source
192 # location. No need to have one under /build/<board>.
193 autotest_dir_arg = '--autotest_dir ~/trunk/src/third_party/autotest/files'
194
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800195 profiler_args = GetProfilerArgs(profiler_args)
196 fast_arg = ''
Luis Lozano5d7e21d2015-03-20 17:57:36 -0700197 if not profiler_args:
198 # --fast works unless we are doing profiling (autotest limitation).
199 # --fast avoids unnecessary copies of syslogs.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800200 fast_arg = '--fast'
201 args_string = ''
cmticee5a746f2013-11-25 14:57:10 -0500202 if test_args:
203 # Strip double quotes off args (so we can wrap them in single
204 # quotes, to pass through to Telemetry).
205 if test_args[0] == '"' and test_args[-1] == '"':
206 test_args = test_args[1:-1]
207 args_string = "test_args='%s'" % test_args
Luis Lozano004bccb2015-03-20 18:19:58 -0700208
Ting-Yuan Huangbc2d3d12015-07-02 13:09:03 +0800209 cmd = ('{} {} {} --board={} --args="{} run_local={} test={} '
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800210 '{}" {} telemetry_Crosperf'.format(
211 TEST_THAT_PATH, autotest_dir_arg, fast_arg, label.board,
212 args_string, benchmark.run_local, benchmark.test_name,
213 profiler_args, machine))
Luis Lozano5d7e21d2015-03-20 17:57:36 -0700214
Luis Lozano45b53c52015-09-30 11:36:27 -0700215 # Use --no-ns-pid so that cros_sdk does not create a different
216 # process namespace and we can kill process created easily by their
217 # process group.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800218 chrome_root_options = ('--no-ns-pid '
219 '--chrome_root={} --chrome_root_mount={} '
Luis Lozano45b53c52015-09-30 11:36:27 -0700220 "FEATURES=\"-usersandbox\" "
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800221 'CHROME_ROOT={}'.format(label.chrome_src,
222 CHROME_MOUNT_DIR,
223 CHROME_MOUNT_DIR))
224 if self.log_level != 'verbose':
225 self._logger.LogOutput('Running test.')
226 self._logger.LogOutput('CMD: %s' % cmd)
Luis Lozano036c9232015-12-10 10:47:01 -0800227 return self._ce.ChrootRunCommandWOutput(
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800228 label.chromeos_root,
229 cmd,
230 command_terminator=self._ct,
Luis Lozano036c9232015-12-10 10:47:01 -0800231 cros_sdk_options=chrome_root_options)
Caroline Tice92774192013-09-10 16:29:18 -0700232
cmtice226e3e02014-04-27 22:28:42 -0700233 def Telemetry_Run(self, machine, label, benchmark, profiler_args):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800234 telemetry_run_path = ''
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700235 if not os.path.isdir(label.chrome_src):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800236 self._logger.LogFatal('Cannot find chrome src dir to' ' run telemetry.')
cmtice98a53692014-04-16 14:48:47 -0700237 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800238 telemetry_run_path = os.path.join(label.chrome_src, 'src/tools/perf')
cmtice98a53692014-04-16 14:48:47 -0700239 if not os.path.exists(telemetry_run_path):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800240 self._logger.LogFatal('Cannot find %s directory.' % telemetry_run_path)
cmtice98a53692014-04-16 14:48:47 -0700241
cmtice226e3e02014-04-27 22:28:42 -0700242 if profiler_args:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800243 self._logger.LogFatal('Telemetry does not support the perf profiler.')
cmtice226e3e02014-04-27 22:28:42 -0700244
cmtice146058f2015-07-24 14:04:12 -0700245 # Check for and remove temporary file that may have been left by
246 # previous telemetry runs (and which might prevent this run from
247 # working).
Caroline Tice7057cf62015-12-10 12:09:40 -0800248 if not test_flag.GetTestMode():
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800249 self.RemoveTelemetryTempFile(machine, label.chromeos_root)
cmtice146058f2015-07-24 14:04:12 -0700250
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800251 rsa_key = os.path.join(
252 label.chromeos_root,
253 'src/scripts/mod_for_test_scripts/ssh_keys/testing_rsa')
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700254
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800255 cmd = ('cd {0} && '
256 './run_measurement '
257 '--browser=cros-chrome '
258 '--output-format=csv '
259 '--remote={1} '
260 '--identity {2} '
261 '{3} {4}'.format(telemetry_run_path, machine, rsa_key,
262 benchmark.test_name, benchmark.test_args))
263 if self.log_level != 'verbose':
264 self._logger.LogOutput('Running test.')
265 self._logger.LogOutput('CMD: %s' % cmd)
Luis Lozano036c9232015-12-10 10:47:01 -0800266 return self._ce.RunCommandWOutput(cmd, print_to_console=False)
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700267
268 def Terminate(self):
269 self._ct.Terminate()
270
271
272class MockSuiteRunner(object):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800273
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700274 def __init__(self):
Caroline Tice92774192013-09-10 16:29:18 -0700275 self._true = True
Yunlian Jiang04dc5dc2013-04-23 15:05:05 -0700276
Caroline Tice92774192013-09-10 16:29:18 -0700277 def Run(self, *_args):
278 if self._true:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800279 return [0, '', '']
Caroline Tice92774192013-09-10 16:29:18 -0700280 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800281 return [0, '', '']