blob: 91d4e3f1ba078b91fb2f5c6ddc683e67c6972c5a [file] [log] [blame]
Yunlian Jiang14cf5962015-12-11 15:50:14 -08001#!/usr/bin/python2
2"""Script for running nightly compiler tests on ChromeOS.
cmtice46093e52014-12-09 14:59:16 -08003
4This script launches a buildbot to build ChromeOS with the latest compiler on
5a particular board; then it finds and downloads the trybot image and the
6corresponding official image, and runs crosperf performance tests comparing
7the two. It then generates a report, emails it to the c-compiler-chrome, as
8well as copying the images into the seven-day reports directory.
9"""
10
11# Script to test different toolchains against ChromeOS benchmarks.
Yunlian Jiang14cf5962015-12-11 15:50:14 -080012
13from __future__ import print_function
14
Caroline Ticeeddb0632016-04-14 09:19:02 -070015import argparse
cmticece5ffa42015-02-12 15:18:43 -080016import datetime
cmtice46093e52014-12-09 14:59:16 -080017import os
Luis Lozanoc75fd052016-02-19 17:37:01 -080018import re
cmtice46093e52014-12-09 14:59:16 -080019import sys
20import time
cmtice46093e52014-12-09 14:59:16 -080021
Caroline Ticea8af9a72016-07-20 12:52:59 -070022from cros_utils import command_executer
23from cros_utils import logger
cmtice46093e52014-12-09 14:59:16 -080024
Caroline Ticea8af9a72016-07-20 12:52:59 -070025from cros_utils import buildbot_utils
cmtice46093e52014-12-09 14:59:16 -080026
27# CL that updated GCC ebuilds to use 'next_gcc'.
Luis Lozanof2a3ef42015-12-15 13:49:30 -080028USE_NEXT_GCC_PATCH = '230260'
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070029
Yunlian Jiang2f563562015-08-28 13:54:04 -070030# CL that uses LLVM to build the peppy image.
Luis Lozanof2a3ef42015-12-15 13:49:30 -080031USE_LLVM_PATCH = '295217'
Yunlian Jiang2f563562015-08-28 13:54:04 -070032
Luis Lozanof2a3ef42015-12-15 13:49:30 -080033CROSTC_ROOT = '/usr/local/google/crostc'
34ROLE_ACCOUNT = 'mobiletc-prebuild'
cmtice46093e52014-12-09 14:59:16 -080035TOOLCHAIN_DIR = os.path.dirname(os.path.realpath(__file__))
Luis Lozanof2a3ef42015-12-15 13:49:30 -080036MAIL_PROGRAM = '~/var/bin/mail-sheriff'
Luis Lozanof2a3ef42015-12-15 13:49:30 -080037PENDING_ARCHIVES_DIR = os.path.join(CROSTC_ROOT, 'pending_archives')
38NIGHTLY_TESTS_DIR = os.path.join(CROSTC_ROOT, 'nightly_test_reports')
39
Luis Lozanoc75fd052016-02-19 17:37:01 -080040IMAGE_FS = (r'{board}-{image_type}/{chrome_version}-{tip}\.' +
41 r'{branch}\.{branch_branch}')
42TRYBOT_IMAGE_FS = 'trybot-' + IMAGE_FS + '-{build_id}'
43PFQ_IMAGE_FS = IMAGE_FS + '-rc1'
Manoj Guptaaee96b72016-10-24 13:43:28 -070044IMAGE_RE_GROUPS = {
45 'board': r'(?P<board>\S+)',
46 'image_type': r'(?P<image_type>\S+)',
47 'chrome_version': r'(?P<chrome_version>R\d+)',
48 'tip': r'(?P<tip>\d+)',
49 'branch': r'(?P<branch>\d+)',
50 'branch_branch': r'(?P<branch_branch>\d+)',
51 'build_id': r'(?P<build_id>b\d+)'
52}
Luis Lozanoc75fd052016-02-19 17:37:01 -080053TRYBOT_IMAGE_RE = TRYBOT_IMAGE_FS.format(**IMAGE_RE_GROUPS)
54
cmtice46093e52014-12-09 14:59:16 -080055
Yunlian Jiang14cf5962015-12-11 15:50:14 -080056class ToolchainComparator(object):
57 """Class for doing the nightly tests work."""
cmtice46093e52014-12-09 14:59:16 -080058
Luis Lozanof2a3ef42015-12-15 13:49:30 -080059 def __init__(self,
60 board,
61 remotes,
62 chromeos_root,
63 weekday,
64 patches,
65 noschedv2=False):
cmtice46093e52014-12-09 14:59:16 -080066 self._board = board
67 self._remotes = remotes
68 self._chromeos_root = chromeos_root
69 self._base_dir = os.getcwd()
70 self._ce = command_executer.GetCommandExecuter()
71 self._l = logger.GetLogger()
Luis Lozanof2a3ef42015-12-15 13:49:30 -080072 self._build = '%s-release' % board
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070073 self._patches = patches.split(',')
74 self._patches_string = '_'.join(str(p) for p in self._patches)
Han Shen43494292015-09-14 10:26:40 -070075 self._noschedv2 = noschedv2
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070076
cmtice46093e52014-12-09 14:59:16 -080077 if not weekday:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080078 self._weekday = time.strftime('%a')
cmtice46093e52014-12-09 14:59:16 -080079 else:
80 self._weekday = weekday
cmtice7f3190b2015-05-22 14:14:51 -070081 timestamp = datetime.datetime.strftime(datetime.datetime.now(),
Luis Lozanof2a3ef42015-12-15 13:49:30 -080082 '%Y-%m-%d_%H:%M:%S')
Manoj Guptaaee96b72016-10-24 13:43:28 -070083 self._reports_dir = os.path.join(
84 NIGHTLY_TESTS_DIR,
85 '%s.%s' % (timestamp, board),)
cmtice46093e52014-12-09 14:59:16 -080086
Luis Lozanoc75fd052016-02-19 17:37:01 -080087 def _GetVanillaImageName(self, trybot_image):
88 """Given a trybot artifact name, get corresponding vanilla image name.
cmtice46093e52014-12-09 14:59:16 -080089
Luis Lozano783954f2015-12-21 18:06:29 -080090 Args:
91 trybot_image: artifact name such as
92 'trybot-daisy-release/R40-6394.0.0-b1389'
93
94 Returns:
95 Corresponding official image name, e.g. 'daisy-release/R40-6394.0.0'.
cmtice46093e52014-12-09 14:59:16 -080096 """
Luis Lozanoc75fd052016-02-19 17:37:01 -080097 mo = re.search(TRYBOT_IMAGE_RE, trybot_image)
98 assert mo
99 return IMAGE_FS.replace('\\', '').format(**mo.groupdict())
cmtice46093e52014-12-09 14:59:16 -0800100
Luis Lozanoc75fd052016-02-19 17:37:01 -0800101 def _GetNonAFDOImageName(self, trybot_image):
102 """Given a trybot artifact name, get corresponding non-AFDO image name.
103
104 We get the non-AFDO image from the PFQ builders. This image
105 is not generated for all the boards and, the closest PFQ image
106 was the one build for the previous ChromeOS version (the chrome
107 used in the current version is the one validated in the previous
108 version).
109 The previous ChromeOS does not always exist either. So, we try
110 a couple of versions before.
Luis Lozano783954f2015-12-21 18:06:29 -0800111
112 Args:
113 trybot_image: artifact name such as
114 'trybot-daisy-release/R40-6394.0.0-b1389'
115
116 Returns:
117 Corresponding chrome PFQ image name, e.g.
Luis Lozanoc75fd052016-02-19 17:37:01 -0800118 'daisy-chrome-pfq/R40-6393.0.0-rc1'.
Luis Lozano783954f2015-12-21 18:06:29 -0800119 """
Luis Lozanoc75fd052016-02-19 17:37:01 -0800120 mo = re.search(TRYBOT_IMAGE_RE, trybot_image)
121 assert mo
122 image_dict = mo.groupdict()
123 image_dict['image_type'] = 'chrome-pfq'
124 for _ in xrange(2):
125 image_dict['tip'] = str(int(image_dict['tip']) - 1)
126 nonafdo_image = PFQ_IMAGE_FS.replace('\\', '').format(**image_dict)
127 if buildbot_utils.DoesImageExist(self._chromeos_root, nonafdo_image):
128 return nonafdo_image
129 return ''
Luis Lozano783954f2015-12-21 18:06:29 -0800130
cmtice46093e52014-12-09 14:59:16 -0800131 def _FinishSetup(self):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800132 """Make sure testing_rsa file is properly set up."""
cmtice46093e52014-12-09 14:59:16 -0800133 # Fix protections on ssh key
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800134 command = ('chmod 600 /var/cache/chromeos-cache/distfiles/target'
135 '/chrome-src-internal/src/third_party/chromite/ssh_keys'
136 '/testing_rsa')
cmtice46093e52014-12-09 14:59:16 -0800137 ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
cmtice7f3190b2015-05-22 14:14:51 -0700138 if ret_val != 0:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800139 raise RuntimeError('chmod for testing_rsa failed')
cmtice46093e52014-12-09 14:59:16 -0800140
Luis Lozano783954f2015-12-21 18:06:29 -0800141 def _TestImages(self, trybot_image, vanilla_image, nonafdo_image):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800142 """Create crosperf experiment file.
cmtice46093e52014-12-09 14:59:16 -0800143
Luis Lozano783954f2015-12-21 18:06:29 -0800144 Given the names of the trybot, vanilla and non-AFDO images, create the
cmtice46093e52014-12-09 14:59:16 -0800145 appropriate crosperf experiment file and launch crosperf on it.
146 """
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800147 experiment_file_dir = os.path.join(self._chromeos_root, '..', self._weekday)
148 experiment_file_name = '%s_toolchain_experiment.txt' % self._board
Yunlian Jiang2f563562015-08-28 13:54:04 -0700149
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800150 compiler_string = 'gcc'
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800151 if USE_LLVM_PATCH in self._patches_string:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800152 experiment_file_name = '%s_llvm_experiment.txt' % self._board
153 compiler_string = 'llvm'
Yunlian Jiang2f563562015-08-28 13:54:04 -0700154
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800155 experiment_file = os.path.join(experiment_file_dir, experiment_file_name)
cmtice46093e52014-12-09 14:59:16 -0800156 experiment_header = """
157 board: %s
158 remote: %s
Luis Lozanoe1efeb82015-06-16 16:35:44 -0700159 retries: 1
cmtice46093e52014-12-09 14:59:16 -0800160 """ % (self._board, self._remotes)
161 experiment_tests = """
Luis Lozano1489d642015-12-08 10:08:19 -0800162 benchmark: all_toolchain_perf {
cmtice46093e52014-12-09 14:59:16 -0800163 suite: telemetry_Crosperf
164 iterations: 3
165 }
Caroline Ticee82513b2016-10-27 12:45:15 -0700166
167 benchmark: page_cycler_v2.typical_25 {
168 suite: telemetry_Crosperf
169 iterations: 2
170 run_local: False
171 retries: 0
172 }
cmtice46093e52014-12-09 14:59:16 -0800173 """
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800174
175 with open(experiment_file, 'w') as f:
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800176 f.write(experiment_header)
177 f.write(experiment_tests)
cmtice46093e52014-12-09 14:59:16 -0800178
179 # Now add vanilla to test file.
180 official_image = """
181 vanilla_image {
182 chromeos_root: %s
183 build: %s
Caroline Ticeddde5052015-09-23 09:43:35 -0700184 compiler: gcc
cmtice46093e52014-12-09 14:59:16 -0800185 }
186 """ % (self._chromeos_root, vanilla_image)
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800187 f.write(official_image)
cmtice46093e52014-12-09 14:59:16 -0800188
Luis Lozano783954f2015-12-21 18:06:29 -0800189 # Now add non-AFDO image to test file.
Luis Lozano439f2b72016-01-08 11:56:02 -0800190 if nonafdo_image:
191 official_nonafdo_image = """
Luis Lozano783954f2015-12-21 18:06:29 -0800192 nonafdo_image {
193 chromeos_root: %s
194 build: %s
195 compiler: gcc
196 }
197 """ % (self._chromeos_root, nonafdo_image)
Luis Lozano439f2b72016-01-08 11:56:02 -0800198 f.write(official_nonafdo_image)
Luis Lozano783954f2015-12-21 18:06:29 -0800199
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800200 label_string = '%s_trybot_image' % compiler_string
Caroline Tice80eab982015-11-04 14:03:14 -0800201 if USE_NEXT_GCC_PATCH in self._patches:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800202 label_string = 'gcc_next_trybot_image'
Caroline Tice80eab982015-11-04 14:03:14 -0800203
cmtice46093e52014-12-09 14:59:16 -0800204 experiment_image = """
Caroline Tice80eab982015-11-04 14:03:14 -0800205 %s {
cmtice46093e52014-12-09 14:59:16 -0800206 chromeos_root: %s
207 build: %s
Caroline Ticeddde5052015-09-23 09:43:35 -0700208 compiler: %s
cmtice46093e52014-12-09 14:59:16 -0800209 }
Caroline Tice80eab982015-11-04 14:03:14 -0800210 """ % (label_string, self._chromeos_root, trybot_image,
211 compiler_string)
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800212 f.write(experiment_image)
cmtice46093e52014-12-09 14:59:16 -0800213
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800214 crosperf = os.path.join(TOOLCHAIN_DIR, 'crosperf', 'crosperf')
Han Shen43494292015-09-14 10:26:40 -0700215 noschedv2_opts = '--noschedv2' if self._noschedv2 else ''
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800216 command = ('{crosperf} --no_email=True --results_dir={r_dir} '
217 '--json_report=True {noschedv2_opts} {exp_file}').format(
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800218 crosperf=crosperf,
219 r_dir=self._reports_dir,
220 noschedv2_opts=noschedv2_opts,
221 exp_file=experiment_file)
cmticeaa700b02015-06-12 13:26:47 -0700222
cmtice46093e52014-12-09 14:59:16 -0800223 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700224 if ret != 0:
Manoj Guptaaee96b72016-10-24 13:43:28 -0700225 raise RuntimeError('Crosperf execution error!')
Caroline Ticeebbc3da2015-09-03 10:27:20 -0700226 else:
227 # Copy json report to pending archives directory.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800228 command = 'cp %s/*.json %s/.' % (self._reports_dir, PENDING_ARCHIVES_DIR)
Caroline Ticeebbc3da2015-09-03 10:27:20 -0700229 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700230 return
cmtice46093e52014-12-09 14:59:16 -0800231
cmtice7f3190b2015-05-22 14:14:51 -0700232 def _SendEmail(self):
233 """Find email message generated by crosperf and send it."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800234 filename = os.path.join(self._reports_dir, 'msg_body.html')
cmtice7f3190b2015-05-22 14:14:51 -0700235 if (os.path.exists(filename) and
236 os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800237 email_title = 'buildbot test results'
Yunlian Jiang2f563562015-08-28 13:54:04 -0700238 if self._patches_string == USE_LLVM_PATCH:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800239 email_title = 'buildbot llvm test results'
240 command = ('cat %s | %s -s "%s, %s" -team -html' %
241 (filename, MAIL_PROGRAM, email_title, self._board))
cmtice7f3190b2015-05-22 14:14:51 -0700242 self._ce.RunCommand(command)
cmtice46093e52014-12-09 14:59:16 -0800243
244 def DoAll(self):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800245 """Main function inside ToolchainComparator class.
cmtice46093e52014-12-09 14:59:16 -0800246
247 Launch trybot, get image names, create crosperf experiment file, run
248 crosperf, and copy images into seven-day report directories.
249 """
cmticece5ffa42015-02-12 15:18:43 -0800250 date_str = datetime.date.today()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800251 description = 'master_%s_%s_%s' % (self._patches_string, self._build,
Han Shenfe054f12015-02-18 15:00:13 -0800252 date_str)
Manoj Guptaaee96b72016-10-24 13:43:28 -0700253 trybot_image = buildbot_utils.GetTrybotImage(
254 self._chromeos_root,
255 self._build,
256 self._patches,
257 description,
258 other_flags=['--notests'],
259 build_toolchain=True)
cmtice46093e52014-12-09 14:59:16 -0800260
cmticed54f9802015-02-05 11:04:11 -0800261 if len(trybot_image) == 0:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800262 self._l.LogError('Unable to find trybot_image for %s!' % description)
Luis Lozano7f20acb2015-11-04 17:15:08 -0800263 return 1
Luis Lozano783954f2015-12-21 18:06:29 -0800264
Luis Lozanoc75fd052016-02-19 17:37:01 -0800265 vanilla_image = self._GetVanillaImageName(trybot_image)
266 nonafdo_image = self._GetNonAFDOImageName(trybot_image)
Luis Lozano783954f2015-12-21 18:06:29 -0800267
Yunlian Jiang56f13762016-01-06 12:56:24 -0800268 # The trybot image is ready here, in some cases, the vanilla image
269 # is not ready, so we need to make sure vanilla image is available.
270 buildbot_utils.WaitForImage(self._chromeos_root, vanilla_image)
Luis Lozano783954f2015-12-21 18:06:29 -0800271 print('trybot_image: %s' % trybot_image)
272 print('vanilla_image: %s' % vanilla_image)
273 print('nonafdo_image: %s' % nonafdo_image)
Luis Lozanoc75fd052016-02-19 17:37:01 -0800274
cmtice46093e52014-12-09 14:59:16 -0800275 if os.getlogin() == ROLE_ACCOUNT:
276 self._FinishSetup()
277
Luis Lozano783954f2015-12-21 18:06:29 -0800278 self._TestImages(trybot_image, vanilla_image, nonafdo_image)
cmtice7f3190b2015-05-22 14:14:51 -0700279 self._SendEmail()
cmtice46093e52014-12-09 14:59:16 -0800280 return 0
281
282
283def Main(argv):
284 """The main function."""
285
286 # Common initializations
287 command_executer.InitCommandExecuter()
Caroline Ticeeddb0632016-04-14 09:19:02 -0700288 parser = argparse.ArgumentParser()
Manoj Guptaaee96b72016-10-24 13:43:28 -0700289 parser.add_argument(
290 '--remote', dest='remote', help='Remote machines to run tests on.')
291 parser.add_argument(
292 '--board', dest='board', default='x86-zgb', help='The target board.')
293 parser.add_argument(
294 '--chromeos_root',
295 dest='chromeos_root',
296 help='The chromeos root from which to run tests.')
297 parser.add_argument(
298 '--weekday',
299 default='',
300 dest='weekday',
301 help='The day of the week for which to run tests.')
302 parser.add_argument(
303 '--patch',
304 dest='patches',
305 help='The patches to use for the testing, '
306 "seprate the patch numbers with ',' "
307 'for more than one patches.')
308 parser.add_argument(
309 '--noschedv2',
310 dest='noschedv2',
311 action='store_true',
312 default=False,
313 help='Pass --noschedv2 to crosperf.')
Han Shen36413122015-08-28 11:05:40 -0700314
Caroline Ticeeddb0632016-04-14 09:19:02 -0700315 options = parser.parse_args(argv[1:])
cmtice46093e52014-12-09 14:59:16 -0800316 if not options.board:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800317 print('Please give a board.')
cmtice46093e52014-12-09 14:59:16 -0800318 return 1
319 if not options.remote:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800320 print('Please give at least one remote machine.')
cmtice46093e52014-12-09 14:59:16 -0800321 return 1
322 if not options.chromeos_root:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800323 print('Please specify the ChromeOS root directory.')
cmtice46093e52014-12-09 14:59:16 -0800324 return 1
Yunlian Jiang76259e62015-08-21 08:44:31 -0700325 if options.patches:
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700326 patches = options.patches
327 else:
328 patches = USE_NEXT_GCC_PATCH
Yunlian Jiange52838c2015-08-20 14:32:37 -0700329
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800330 fc = ToolchainComparator(options.board, options.remote, options.chromeos_root,
331 options.weekday, patches, options.noschedv2)
cmtice46093e52014-12-09 14:59:16 -0800332 return fc.DoAll()
333
334
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800335if __name__ == '__main__':
cmtice46093e52014-12-09 14:59:16 -0800336 retval = Main(sys.argv)
337 sys.exit(retval)