blob: ea6099b6e5ddca0b9c03f5817add22e1a85cfeb9 [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
cmticece5ffa42015-02-12 15:18:43 -080015import datetime
cmtice46093e52014-12-09 14:59:16 -080016import optparse
17import os
18import sys
19import time
cmtice46093e52014-12-09 14:59:16 -080020
21from utils import command_executer
22from utils import logger
23
24from utils import buildbot_utils
25
26# CL that updated GCC ebuilds to use 'next_gcc'.
Luis Lozanof2a3ef42015-12-15 13:49:30 -080027USE_NEXT_GCC_PATCH = '230260'
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070028
Yunlian Jiang2f563562015-08-28 13:54:04 -070029# CL that uses LLVM to build the peppy image.
Luis Lozanof2a3ef42015-12-15 13:49:30 -080030USE_LLVM_PATCH = '295217'
Yunlian Jiang2f563562015-08-28 13:54:04 -070031
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070032# The boards on which we run weekly reports
Luis Lozanof2a3ef42015-12-15 13:49:30 -080033WEEKLY_REPORT_BOARDS = ['lumpy']
cmtice46093e52014-12-09 14:59:16 -080034
Luis Lozanof2a3ef42015-12-15 13:49:30 -080035CROSTC_ROOT = '/usr/local/google/crostc'
36ROLE_ACCOUNT = 'mobiletc-prebuild'
cmtice46093e52014-12-09 14:59:16 -080037TOOLCHAIN_DIR = os.path.dirname(os.path.realpath(__file__))
Luis Lozanof2a3ef42015-12-15 13:49:30 -080038MAIL_PROGRAM = '~/var/bin/mail-sheriff'
39WEEKLY_REPORTS_ROOT = os.path.join(CROSTC_ROOT, 'weekly_test_data')
40PENDING_ARCHIVES_DIR = os.path.join(CROSTC_ROOT, 'pending_archives')
41NIGHTLY_TESTS_DIR = os.path.join(CROSTC_ROOT, 'nightly_test_reports')
42
cmtice46093e52014-12-09 14:59:16 -080043
Yunlian Jiang14cf5962015-12-11 15:50:14 -080044class ToolchainComparator(object):
45 """Class for doing the nightly tests work."""
cmtice46093e52014-12-09 14:59:16 -080046
Luis Lozanof2a3ef42015-12-15 13:49:30 -080047 def __init__(self,
48 board,
49 remotes,
50 chromeos_root,
51 weekday,
52 patches,
53 noschedv2=False):
cmtice46093e52014-12-09 14:59:16 -080054 self._board = board
55 self._remotes = remotes
56 self._chromeos_root = chromeos_root
57 self._base_dir = os.getcwd()
58 self._ce = command_executer.GetCommandExecuter()
59 self._l = logger.GetLogger()
Luis Lozanof2a3ef42015-12-15 13:49:30 -080060 self._build = '%s-release' % board
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070061 self._patches = patches.split(',')
62 self._patches_string = '_'.join(str(p) for p in self._patches)
Han Shen43494292015-09-14 10:26:40 -070063 self._noschedv2 = noschedv2
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070064
cmtice46093e52014-12-09 14:59:16 -080065 if not weekday:
Luis Lozanof2a3ef42015-12-15 13:49:30 -080066 self._weekday = time.strftime('%a')
cmtice46093e52014-12-09 14:59:16 -080067 else:
68 self._weekday = weekday
cmtice7f3190b2015-05-22 14:14:51 -070069 timestamp = datetime.datetime.strftime(datetime.datetime.now(),
Luis Lozanof2a3ef42015-12-15 13:49:30 -080070 '%Y-%m-%d_%H:%M:%S')
Caroline Ticeebbc3da2015-09-03 10:27:20 -070071 self._reports_dir = os.path.join(NIGHTLY_TESTS_DIR,
Luis Lozanof2a3ef42015-12-15 13:49:30 -080072 '%s.%s' % (timestamp, board),)
cmtice46093e52014-12-09 14:59:16 -080073
74 def _ParseVanillaImage(self, trybot_image):
Yunlian Jiang14cf5962015-12-11 15:50:14 -080075 """Parse a trybot artifact name to get corresponding vanilla image.
cmtice46093e52014-12-09 14:59:16 -080076
Luis Lozano783954f2015-12-21 18:06:29 -080077 Args:
78 trybot_image: artifact name such as
79 'trybot-daisy-release/R40-6394.0.0-b1389'
80
81 Returns:
82 Corresponding official image name, e.g. 'daisy-release/R40-6394.0.0'.
cmtice46093e52014-12-09 14:59:16 -080083 """
84 start_pos = trybot_image.find(self._build)
Luis Lozano783954f2015-12-21 18:06:29 -080085 assert start_pos != -1
Luis Lozanof2a3ef42015-12-15 13:49:30 -080086 end_pos = trybot_image.rfind('-b')
Luis Lozano783954f2015-12-21 18:06:29 -080087 assert end_pos != -1
cmtice46093e52014-12-09 14:59:16 -080088 vanilla_image = trybot_image[start_pos:end_pos]
89 return vanilla_image
90
Luis Lozano783954f2015-12-21 18:06:29 -080091 def _ParseNonAFDOImage(self, trybot_image):
92 """Parse a trybot artifact name to get corresponding non-AFDO image.
93
94 Args:
95 trybot_image: artifact name such as
96 'trybot-daisy-release/R40-6394.0.0-b1389'
97
98 Returns:
99 Corresponding chrome PFQ image name, e.g.
100 'daisy-chrome-pfq/R40-6394.0.0-rc1'.
101 """
102 start_pos = trybot_image.find(self._build)
103 assert start_pos != -1
104 end_pos = trybot_image.rfind('-b')
105 assert end_pos != -1
106 nonafdo_image = trybot_image[start_pos:end_pos]
107 pfq_suffix = '-chrome-pfq'
108 nonafdo_image = nonafdo_image.replace('-release', pfq_suffix) + '-rc1'
109 assert nonafdo_image.find(pfq_suffix) != -1
110 return nonafdo_image
111
cmtice46093e52014-12-09 14:59:16 -0800112 def _FinishSetup(self):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800113 """Make sure testing_rsa file is properly set up."""
cmtice46093e52014-12-09 14:59:16 -0800114 # Fix protections on ssh key
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800115 command = ('chmod 600 /var/cache/chromeos-cache/distfiles/target'
116 '/chrome-src-internal/src/third_party/chromite/ssh_keys'
117 '/testing_rsa')
cmtice46093e52014-12-09 14:59:16 -0800118 ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
cmtice7f3190b2015-05-22 14:14:51 -0700119 if ret_val != 0:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800120 raise RuntimeError('chmod for testing_rsa failed')
cmtice46093e52014-12-09 14:59:16 -0800121
Luis Lozano783954f2015-12-21 18:06:29 -0800122 def _TestImages(self, trybot_image, vanilla_image, nonafdo_image):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800123 """Create crosperf experiment file.
cmtice46093e52014-12-09 14:59:16 -0800124
Luis Lozano783954f2015-12-21 18:06:29 -0800125 Given the names of the trybot, vanilla and non-AFDO images, create the
cmtice46093e52014-12-09 14:59:16 -0800126 appropriate crosperf experiment file and launch crosperf on it.
127 """
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800128 experiment_file_dir = os.path.join(self._chromeos_root, '..', self._weekday)
129 experiment_file_name = '%s_toolchain_experiment.txt' % self._board
Yunlian Jiang2f563562015-08-28 13:54:04 -0700130
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800131 compiler_string = 'gcc'
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800132 if USE_LLVM_PATCH in self._patches_string:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800133 experiment_file_name = '%s_llvm_experiment.txt' % self._board
134 compiler_string = 'llvm'
Yunlian Jiang2f563562015-08-28 13:54:04 -0700135
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800136 experiment_file = os.path.join(experiment_file_dir, experiment_file_name)
cmtice46093e52014-12-09 14:59:16 -0800137 experiment_header = """
138 board: %s
139 remote: %s
Luis Lozanoe1efeb82015-06-16 16:35:44 -0700140 retries: 1
cmtice46093e52014-12-09 14:59:16 -0800141 """ % (self._board, self._remotes)
142 experiment_tests = """
Luis Lozano1489d642015-12-08 10:08:19 -0800143 benchmark: all_toolchain_perf {
cmtice46093e52014-12-09 14:59:16 -0800144 suite: telemetry_Crosperf
145 iterations: 3
146 }
147 """
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800148
149 with open(experiment_file, 'w') as f:
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800150 f.write(experiment_header)
151 f.write(experiment_tests)
cmtice46093e52014-12-09 14:59:16 -0800152
153 # Now add vanilla to test file.
154 official_image = """
155 vanilla_image {
156 chromeos_root: %s
157 build: %s
Caroline Ticeddde5052015-09-23 09:43:35 -0700158 compiler: gcc
cmtice46093e52014-12-09 14:59:16 -0800159 }
160 """ % (self._chromeos_root, vanilla_image)
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800161 f.write(official_image)
cmtice46093e52014-12-09 14:59:16 -0800162
Luis Lozano783954f2015-12-21 18:06:29 -0800163 # Now add non-AFDO image to test file.
164 official_nonafdo_image = """
165 nonafdo_image {
166 chromeos_root: %s
167 build: %s
168 compiler: gcc
169 }
170 """ % (self._chromeos_root, nonafdo_image)
171 f.write(official_nonafdo_image)
172
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800173 label_string = '%s_trybot_image' % compiler_string
Caroline Tice80eab982015-11-04 14:03:14 -0800174 if USE_NEXT_GCC_PATCH in self._patches:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800175 label_string = 'gcc_next_trybot_image'
Caroline Tice80eab982015-11-04 14:03:14 -0800176
cmtice46093e52014-12-09 14:59:16 -0800177 experiment_image = """
Caroline Tice80eab982015-11-04 14:03:14 -0800178 %s {
cmtice46093e52014-12-09 14:59:16 -0800179 chromeos_root: %s
180 build: %s
Caroline Ticeddde5052015-09-23 09:43:35 -0700181 compiler: %s
cmtice46093e52014-12-09 14:59:16 -0800182 }
Caroline Tice80eab982015-11-04 14:03:14 -0800183 """ % (label_string, self._chromeos_root, trybot_image,
184 compiler_string)
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800185 f.write(experiment_image)
cmtice46093e52014-12-09 14:59:16 -0800186
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800187 crosperf = os.path.join(TOOLCHAIN_DIR, 'crosperf', 'crosperf')
Han Shen43494292015-09-14 10:26:40 -0700188 noschedv2_opts = '--noschedv2' if self._noschedv2 else ''
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800189 command = ('{crosperf} --no_email=True --results_dir={r_dir} '
190 '--json_report=True {noschedv2_opts} {exp_file}').format(
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800191 crosperf=crosperf,
192 r_dir=self._reports_dir,
193 noschedv2_opts=noschedv2_opts,
194 exp_file=experiment_file)
cmticeaa700b02015-06-12 13:26:47 -0700195
cmtice46093e52014-12-09 14:59:16 -0800196 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700197 if ret != 0:
198 raise RuntimeError("Couldn't run crosperf!")
Caroline Ticeebbc3da2015-09-03 10:27:20 -0700199 else:
200 # Copy json report to pending archives directory.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800201 command = 'cp %s/*.json %s/.' % (self._reports_dir, PENDING_ARCHIVES_DIR)
Caroline Ticeebbc3da2015-09-03 10:27:20 -0700202 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700203 return
cmtice46093e52014-12-09 14:59:16 -0800204
Luis Lozano783954f2015-12-21 18:06:29 -0800205 def _CopyWeeklyReportFiles(self, trybot_image, vanilla_image, nonafdo_image):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800206 """Put files in place for running seven-day reports.
cmtice46093e52014-12-09 14:59:16 -0800207
208 Create tar files of the custom and official images and copy them
209 to the weekly reports directory, so they exist when the weekly report
210 gets generated. IMPORTANT NOTE: This function must run *after*
211 crosperf has been run; otherwise the vanilla images will not be there.
212 """
213
214 dry_run = False
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800215 if os.getlogin() != ROLE_ACCOUNT:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800216 self._l.LogOutput('Running this from non-role account; not copying '
217 'tar files for weekly reports.')
cmtice46093e52014-12-09 14:59:16 -0800218 dry_run = True
219
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800220 images_path = os.path.join(
221 os.path.realpath(self._chromeos_root), 'chroot/tmp')
cmtice46093e52014-12-09 14:59:16 -0800222
223 data_dir = os.path.join(WEEKLY_REPORTS_ROOT, self._board)
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800224 dest_dir = os.path.join(data_dir, self._weekday)
cmtice46093e52014-12-09 14:59:16 -0800225 if not os.path.exists(dest_dir):
226 os.makedirs(dest_dir)
227
228 # Make sure dest_dir is empty (clean out last week's data).
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800229 cmd = 'cd %s; rm -Rf %s_*_image*' % (dest_dir, self._weekday)
cmtice46093e52014-12-09 14:59:16 -0800230 if dry_run:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800231 print('CMD: %s' % cmd)
cmtice46093e52014-12-09 14:59:16 -0800232 else:
233 self._ce.RunCommand(cmd)
234
235 # Now create new tar files and copy them over.
Luis Lozano783954f2015-12-21 18:06:29 -0800236 labels = ['test', 'vanilla', 'nonafdo']
cmtice46093e52014-12-09 14:59:16 -0800237 for label_name in labels:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800238 if label_name == 'test':
cmtice46093e52014-12-09 14:59:16 -0800239 test_path = trybot_image
Luis Lozano783954f2015-12-21 18:06:29 -0800240 elif label_name == 'vanilla':
cmtice46093e52014-12-09 14:59:16 -0800241 test_path = vanilla_image
Luis Lozano783954f2015-12-21 18:06:29 -0800242 else:
243 test_path = nonafdo_image
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800244 tar_file_name = '%s_%s_image.tar' % (self._weekday, label_name)
245 cmd = ('cd %s; tar -cvf %s %s/chromiumos_test_image.bin; '
246 'cp %s %s/.') % (images_path, tar_file_name, test_path,
247 tar_file_name, dest_dir)
cmtice46093e52014-12-09 14:59:16 -0800248 if dry_run:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800249 print('CMD: %s' % cmd)
cmtice46093e52014-12-09 14:59:16 -0800250 tar_ret = 0
251 else:
252 tar_ret = self._ce.RunCommand(cmd)
253 if tar_ret:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800254 self._l.LogOutput('Error while creating/copying test tar file(%s).' %
255 tar_file_name)
cmtice46093e52014-12-09 14:59:16 -0800256
cmtice7f3190b2015-05-22 14:14:51 -0700257 def _SendEmail(self):
258 """Find email message generated by crosperf and send it."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800259 filename = os.path.join(self._reports_dir, 'msg_body.html')
cmtice7f3190b2015-05-22 14:14:51 -0700260 if (os.path.exists(filename) and
261 os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800262 email_title = 'buildbot test results'
Yunlian Jiang2f563562015-08-28 13:54:04 -0700263 if self._patches_string == USE_LLVM_PATCH:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800264 email_title = 'buildbot llvm test results'
265 command = ('cat %s | %s -s "%s, %s" -team -html' %
266 (filename, MAIL_PROGRAM, email_title, self._board))
cmtice7f3190b2015-05-22 14:14:51 -0700267 self._ce.RunCommand(command)
cmtice46093e52014-12-09 14:59:16 -0800268
269 def DoAll(self):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800270 """Main function inside ToolchainComparator class.
cmtice46093e52014-12-09 14:59:16 -0800271
272 Launch trybot, get image names, create crosperf experiment file, run
273 crosperf, and copy images into seven-day report directories.
274 """
cmticece5ffa42015-02-12 15:18:43 -0800275 date_str = datetime.date.today()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800276 description = 'master_%s_%s_%s' % (self._patches_string, self._build,
Han Shenfe054f12015-02-18 15:00:13 -0800277 date_str)
cmtice46093e52014-12-09 14:59:16 -0800278 trybot_image = buildbot_utils.GetTrybotImage(self._chromeos_root,
279 self._build,
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700280 self._patches,
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700281 description,
282 build_toolchain=True)
cmtice46093e52014-12-09 14:59:16 -0800283
cmticed54f9802015-02-05 11:04:11 -0800284 if len(trybot_image) == 0:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800285 self._l.LogError('Unable to find trybot_image for %s!' % description)
Luis Lozano7f20acb2015-11-04 17:15:08 -0800286 return 1
Luis Lozano783954f2015-12-21 18:06:29 -0800287
288 vanilla_image = self._ParseVanillaImage(trybot_image)
289 nonafdo_image = self._ParseNonAFDOImage(trybot_image)
290
Yunlian Jiang56f13762016-01-06 12:56:24 -0800291 # The trybot image is ready here, in some cases, the vanilla image
292 # is not ready, so we need to make sure vanilla image is available.
293 buildbot_utils.WaitForImage(self._chromeos_root, vanilla_image)
Luis Lozano783954f2015-12-21 18:06:29 -0800294 print('trybot_image: %s' % trybot_image)
295 print('vanilla_image: %s' % vanilla_image)
296 print('nonafdo_image: %s' % nonafdo_image)
cmtice46093e52014-12-09 14:59:16 -0800297 if os.getlogin() == ROLE_ACCOUNT:
298 self._FinishSetup()
299
Luis Lozano783954f2015-12-21 18:06:29 -0800300 self._TestImages(trybot_image, vanilla_image, nonafdo_image)
cmtice7f3190b2015-05-22 14:14:51 -0700301 self._SendEmail()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700302 if (self._patches_string == USE_NEXT_GCC_PATCH and
303 self._board in WEEKLY_REPORT_BOARDS):
Luis Lozano7f20acb2015-11-04 17:15:08 -0800304 # Only try to copy the image files if the test runs ran successfully.
Luis Lozano783954f2015-12-21 18:06:29 -0800305 self._CopyWeeklyReportFiles(trybot_image, vanilla_image, nonafdo_image)
cmtice46093e52014-12-09 14:59:16 -0800306 return 0
307
308
309def Main(argv):
310 """The main function."""
311
312 # Common initializations
313 command_executer.InitCommandExecuter()
314 parser = optparse.OptionParser()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800315 parser.add_option('--remote',
316 dest='remote',
317 help='Remote machines to run tests on.')
318 parser.add_option('--board',
319 dest='board',
320 default='x86-zgb',
321 help='The target board.')
322 parser.add_option('--chromeos_root',
323 dest='chromeos_root',
324 help='The chromeos root from which to run tests.')
325 parser.add_option('--weekday',
326 default='',
327 dest='weekday',
328 help='The day of the week for which to run tests.')
329 parser.add_option('--patch',
330 dest='patches',
331 help='The patches to use for the testing, '
Yunlian Jiange52838c2015-08-20 14:32:37 -0700332 "seprate the patch numbers with ',' "
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800333 'for more than one patches.')
334 parser.add_option('--noschedv2',
335 dest='noschedv2',
336 action='store_true',
Han Shen36413122015-08-28 11:05:40 -0700337 default=False,
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800338 help='Pass --noschedv2 to crosperf.')
Han Shen36413122015-08-28 11:05:40 -0700339
cmtice46093e52014-12-09 14:59:16 -0800340 options, _ = parser.parse_args(argv)
341 if not options.board:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800342 print('Please give a board.')
cmtice46093e52014-12-09 14:59:16 -0800343 return 1
344 if not options.remote:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800345 print('Please give at least one remote machine.')
cmtice46093e52014-12-09 14:59:16 -0800346 return 1
347 if not options.chromeos_root:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800348 print('Please specify the ChromeOS root directory.')
cmtice46093e52014-12-09 14:59:16 -0800349 return 1
Yunlian Jiang76259e62015-08-21 08:44:31 -0700350 if options.patches:
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700351 patches = options.patches
352 else:
353 patches = USE_NEXT_GCC_PATCH
Yunlian Jiange52838c2015-08-20 14:32:37 -0700354
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800355 fc = ToolchainComparator(options.board, options.remote, options.chromeos_root,
356 options.weekday, patches, options.noschedv2)
cmtice46093e52014-12-09 14:59:16 -0800357 return fc.DoAll()
358
359
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800360if __name__ == '__main__':
cmtice46093e52014-12-09 14:59:16 -0800361 retval = Main(sys.argv)
362 sys.exit(retval)