blob: 8b5bce7bdfdffe6a3dd0fd2eabea9a268f894551 [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'.
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070027USE_NEXT_GCC_PATCH = "230260"
28
Yunlian Jiang2f563562015-08-28 13:54:04 -070029# CL that uses LLVM to build the peppy image.
30USE_LLVM_PATCH = "295217"
31
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070032# The boards on which we run weekly reports
33WEEKLY_REPORT_BOARDS = ["lumpy"]
cmtice46093e52014-12-09 14:59:16 -080034
Caroline Ticeebbc3da2015-09-03 10:27:20 -070035CROSTC_ROOT = "/usr/local/google/crostc"
cmtice46093e52014-12-09 14:59:16 -080036ROLE_ACCOUNT = "mobiletc-prebuild"
37TOOLCHAIN_DIR = os.path.dirname(os.path.realpath(__file__))
cmtice7f3190b2015-05-22 14:14:51 -070038MAIL_PROGRAM = "~/var/bin/mail-sheriff"
Caroline Ticeebbc3da2015-09-03 10:27:20 -070039WEEKLY_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")
cmtice46093e52014-12-09 14:59:16 -080042
Yunlian Jiang14cf5962015-12-11 15:50:14 -080043class ToolchainComparator(object):
44 """Class for doing the nightly tests work."""
cmtice46093e52014-12-09 14:59:16 -080045
Yunlian Jiang14cf5962015-12-11 15:50:14 -080046 def __init__(self, board, remotes, chromeos_root, weekday,
47 patches, noschedv2=False):
cmtice46093e52014-12-09 14:59:16 -080048 self._board = board
49 self._remotes = remotes
50 self._chromeos_root = chromeos_root
51 self._base_dir = os.getcwd()
52 self._ce = command_executer.GetCommandExecuter()
53 self._l = logger.GetLogger()
54 self._build = "%s-release" % board
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070055 self._patches = patches.split(',')
56 self._patches_string = '_'.join(str(p) for p in self._patches)
Han Shen43494292015-09-14 10:26:40 -070057 self._noschedv2 = noschedv2
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070058
cmtice46093e52014-12-09 14:59:16 -080059 if not weekday:
60 self._weekday = time.strftime("%a")
61 else:
62 self._weekday = weekday
cmtice7f3190b2015-05-22 14:14:51 -070063 timestamp = datetime.datetime.strftime(datetime.datetime.now(),
64 "%Y-%m-%d_%H:%M:%S")
Caroline Ticeebbc3da2015-09-03 10:27:20 -070065 self._reports_dir = os.path.join(NIGHTLY_TESTS_DIR,
Yunlian Jiang14cf5962015-12-11 15:50:14 -080066 "%s.%s" % (timestamp, board),
67 )
cmtice46093e52014-12-09 14:59:16 -080068
69 def _ParseVanillaImage(self, trybot_image):
Yunlian Jiang14cf5962015-12-11 15:50:14 -080070 """Parse a trybot artifact name to get corresponding vanilla image.
cmtice46093e52014-12-09 14:59:16 -080071
72 This function takes an artifact name, such as
73 'trybot-daisy-release/R40-6394.0.0-b1389', and returns the
74 corresponding official build name, e.g. 'daisy-release/R40-6394.0.0'.
75 """
76 start_pos = trybot_image.find(self._build)
77 end_pos = trybot_image.rfind("-b")
78 vanilla_image = trybot_image[start_pos:end_pos]
79 return vanilla_image
80
cmtice46093e52014-12-09 14:59:16 -080081 def _FinishSetup(self):
Yunlian Jiang14cf5962015-12-11 15:50:14 -080082 """Make sure testing_rsa file is properly set up."""
cmtice46093e52014-12-09 14:59:16 -080083 # Fix protections on ssh key
84 command = ("chmod 600 /var/cache/chromeos-cache/distfiles/target"
85 "/chrome-src-internal/src/third_party/chromite/ssh_keys"
86 "/testing_rsa")
87 ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
cmtice7f3190b2015-05-22 14:14:51 -070088 if ret_val != 0:
89 raise RuntimeError("chmod for testing_rsa failed")
cmtice46093e52014-12-09 14:59:16 -080090
91 def _TestImages(self, trybot_image, vanilla_image):
Yunlian Jiang14cf5962015-12-11 15:50:14 -080092 """Create crosperf experiment file.
cmtice46093e52014-12-09 14:59:16 -080093
94 Given the names of the trybot and vanilla images, create the
95 appropriate crosperf experiment file and launch crosperf on it.
96 """
Yunlian Jiang14cf5962015-12-11 15:50:14 -080097 experiment_file_dir = os.path.join(self._chromeos_root, "..",
98 self._weekday)
cmtice46093e52014-12-09 14:59:16 -080099 experiment_file_name = "%s_toolchain_experiment.txt" % self._board
Yunlian Jiang2f563562015-08-28 13:54:04 -0700100
Caroline Ticeddde5052015-09-23 09:43:35 -0700101 compiler_string = "gcc"
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800102 if USE_LLVM_PATCH in self._patches_string:
Yunlian Jiang2f563562015-08-28 13:54:04 -0700103 experiment_file_name = "%s_llvm_experiment.txt" % self._board
Caroline Ticeddde5052015-09-23 09:43:35 -0700104 compiler_string = "llvm"
Yunlian Jiang2f563562015-08-28 13:54:04 -0700105
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800106 experiment_file = os.path.join(experiment_file_dir,
107 experiment_file_name)
cmtice46093e52014-12-09 14:59:16 -0800108 experiment_header = """
109 board: %s
110 remote: %s
Luis Lozanoe1efeb82015-06-16 16:35:44 -0700111 retries: 1
cmtice46093e52014-12-09 14:59:16 -0800112 """ % (self._board, self._remotes)
113 experiment_tests = """
Luis Lozano1489d642015-12-08 10:08:19 -0800114 benchmark: all_toolchain_perf {
cmtice46093e52014-12-09 14:59:16 -0800115 suite: telemetry_Crosperf
116 iterations: 3
117 }
118 """
119 with open(experiment_file, "w") as f:
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800120 f.write(experiment_header)
121 f.write(experiment_tests)
cmtice46093e52014-12-09 14:59:16 -0800122
123 # Now add vanilla to test file.
124 official_image = """
125 vanilla_image {
126 chromeos_root: %s
127 build: %s
Caroline Ticeddde5052015-09-23 09:43:35 -0700128 compiler: gcc
cmtice46093e52014-12-09 14:59:16 -0800129 }
130 """ % (self._chromeos_root, vanilla_image)
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800131 f.write(official_image)
cmtice46093e52014-12-09 14:59:16 -0800132
Caroline Tice80eab982015-11-04 14:03:14 -0800133 label_string = "%s_trybot_image" % compiler_string
134 if USE_NEXT_GCC_PATCH in self._patches:
135 label_string = "gcc_next_trybot_image"
136
cmtice46093e52014-12-09 14:59:16 -0800137 experiment_image = """
Caroline Tice80eab982015-11-04 14:03:14 -0800138 %s {
cmtice46093e52014-12-09 14:59:16 -0800139 chromeos_root: %s
140 build: %s
Caroline Ticeddde5052015-09-23 09:43:35 -0700141 compiler: %s
cmtice46093e52014-12-09 14:59:16 -0800142 }
Caroline Tice80eab982015-11-04 14:03:14 -0800143 """ % (label_string, self._chromeos_root, trybot_image,
144 compiler_string)
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800145 f.write(experiment_image)
cmtice46093e52014-12-09 14:59:16 -0800146
147 crosperf = os.path.join(TOOLCHAIN_DIR,
148 "crosperf",
149 "crosperf")
Han Shen43494292015-09-14 10:26:40 -0700150 noschedv2_opts = '--noschedv2' if self._noschedv2 else ''
Han Shen36413122015-08-28 11:05:40 -0700151 command = ("{crosperf} --no_email=True --results_dir={r_dir} "
Han Shen43494292015-09-14 10:26:40 -0700152 "--json_report=True {noschedv2_opts} {exp_file}").format(
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800153 crosperf=crosperf,
154 r_dir=self._reports_dir,
155 noschedv2_opts=noschedv2_opts,
156 exp_file=experiment_file)
cmticeaa700b02015-06-12 13:26:47 -0700157
cmtice46093e52014-12-09 14:59:16 -0800158 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700159 if ret != 0:
160 raise RuntimeError("Couldn't run crosperf!")
Caroline Ticeebbc3da2015-09-03 10:27:20 -0700161 else:
162 # Copy json report to pending archives directory.
163 command = "cp %s/*.json %s/." % (self._reports_dir, PENDING_ARCHIVES_DIR)
164 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700165 return
cmtice46093e52014-12-09 14:59:16 -0800166
167 def _CopyWeeklyReportFiles(self, trybot_image, vanilla_image):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800168 """Put files in place for running seven-day reports.
cmtice46093e52014-12-09 14:59:16 -0800169
170 Create tar files of the custom and official images and copy them
171 to the weekly reports directory, so they exist when the weekly report
172 gets generated. IMPORTANT NOTE: This function must run *after*
173 crosperf has been run; otherwise the vanilla images will not be there.
174 """
175
176 dry_run = False
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800177 if os.getlogin() != ROLE_ACCOUNT:
cmtice46093e52014-12-09 14:59:16 -0800178 self._l.LogOutput("Running this from non-role account; not copying "
179 "tar files for weekly reports.")
180 dry_run = True
181
182 images_path = os.path.join(os.path.realpath(self._chromeos_root),
183 "chroot/tmp")
184
185 data_dir = os.path.join(WEEKLY_REPORTS_ROOT, self._board)
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800186 dest_dir = os.path.join(data_dir, self._weekday)
cmtice46093e52014-12-09 14:59:16 -0800187 if not os.path.exists(dest_dir):
188 os.makedirs(dest_dir)
189
190 # Make sure dest_dir is empty (clean out last week's data).
191 cmd = "cd %s; rm -Rf %s_*_image*" % (dest_dir, self._weekday)
192 if dry_run:
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800193 print("CMD: %s" % cmd)
cmtice46093e52014-12-09 14:59:16 -0800194 else:
195 self._ce.RunCommand(cmd)
196
197 # Now create new tar files and copy them over.
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800198 labels = ["test", "vanilla"]
cmtice46093e52014-12-09 14:59:16 -0800199 for label_name in labels:
200 if label_name == "test":
201 test_path = trybot_image
202 else:
203 test_path = vanilla_image
204 tar_file_name = "%s_%s_image.tar" % (self._weekday, label_name)
Han Shenfe054f12015-02-18 15:00:13 -0800205 cmd = ("cd %s; tar -cvf %s %s/chromiumos_test_image.bin; "
206 "cp %s %s/.") % (images_path,
207 tar_file_name,
208 test_path,
209 tar_file_name,
210 dest_dir)
cmtice46093e52014-12-09 14:59:16 -0800211 if dry_run:
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800212 print("CMD: %s" % cmd)
cmtice46093e52014-12-09 14:59:16 -0800213 tar_ret = 0
214 else:
215 tar_ret = self._ce.RunCommand(cmd)
216 if tar_ret:
217 self._l.LogOutput("Error while creating/copying test tar file(%s)."
218 % tar_file_name)
219
cmtice7f3190b2015-05-22 14:14:51 -0700220 def _SendEmail(self):
221 """Find email message generated by crosperf and send it."""
222 filename = os.path.join(self._reports_dir,
223 "msg_body.html")
224 if (os.path.exists(filename) and
225 os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
Yunlian Jiang2f563562015-08-28 13:54:04 -0700226 email_title = "buildbot test results"
227 if self._patches_string == USE_LLVM_PATCH:
228 email_title = "buildbot llvm test results"
229 command = ('cat %s | %s -s "%s, %s" -team -html'
230 % (filename, MAIL_PROGRAM, email_title, self._board))
cmtice7f3190b2015-05-22 14:14:51 -0700231 self._ce.RunCommand(command)
cmtice46093e52014-12-09 14:59:16 -0800232
233 def DoAll(self):
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800234 """Main function inside ToolchainComparator class.
cmtice46093e52014-12-09 14:59:16 -0800235
236 Launch trybot, get image names, create crosperf experiment file, run
237 crosperf, and copy images into seven-day report directories.
238 """
cmticece5ffa42015-02-12 15:18:43 -0800239 date_str = datetime.date.today()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700240 description = "master_%s_%s_%s" % (self._patches_string,
Han Shenfe054f12015-02-18 15:00:13 -0800241 self._build,
242 date_str)
cmtice46093e52014-12-09 14:59:16 -0800243 trybot_image = buildbot_utils.GetTrybotImage(self._chromeos_root,
244 self._build,
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700245 self._patches,
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700246 description,
247 build_toolchain=True)
cmtice46093e52014-12-09 14:59:16 -0800248
249 vanilla_image = self._ParseVanillaImage(trybot_image)
250
251 print ("trybot_image: %s" % trybot_image)
252 print ("vanilla_image: %s" % vanilla_image)
cmticed54f9802015-02-05 11:04:11 -0800253 if len(trybot_image) == 0:
Luis Lozano7f20acb2015-11-04 17:15:08 -0800254 self._l.LogError("Unable to find trybot_image for %s!" % description)
255 return 1
cmticed54f9802015-02-05 11:04:11 -0800256 if len(vanilla_image) == 0:
Luis Lozano7f20acb2015-11-04 17:15:08 -0800257 self._l.LogError("Unable to find vanilla image for %s!" % description)
258 return 1
cmtice46093e52014-12-09 14:59:16 -0800259 if os.getlogin() == ROLE_ACCOUNT:
260 self._FinishSetup()
261
cmtice7f3190b2015-05-22 14:14:51 -0700262 self._TestImages(trybot_image, vanilla_image)
263 self._SendEmail()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700264 if (self._patches_string == USE_NEXT_GCC_PATCH and
265 self._board in WEEKLY_REPORT_BOARDS):
Luis Lozano7f20acb2015-11-04 17:15:08 -0800266 # Only try to copy the image files if the test runs ran successfully.
267 self._CopyWeeklyReportFiles(trybot_image, vanilla_image)
cmtice46093e52014-12-09 14:59:16 -0800268 return 0
269
270
271def Main(argv):
272 """The main function."""
273
274 # Common initializations
275 command_executer.InitCommandExecuter()
276 parser = optparse.OptionParser()
277 parser.add_option("--remote",
278 dest="remote",
279 help="Remote machines to run tests on.")
280 parser.add_option("--board",
281 dest="board",
282 default="x86-zgb",
283 help="The target board.")
284 parser.add_option("--chromeos_root",
285 dest="chromeos_root",
286 help="The chromeos root from which to run tests.")
287 parser.add_option("--weekday", default="",
288 dest="weekday",
289 help="The day of the week for which to run tests.")
Yunlian Jiange52838c2015-08-20 14:32:37 -0700290 parser.add_option("--patch",
291 dest="patches",
292 help="The patches to use for the testing, "
293 "seprate the patch numbers with ',' "
294 "for more than one patches.")
Han Shen43494292015-09-14 10:26:40 -0700295 parser.add_option("--noschedv2",
296 dest="noschedv2",
Han Shen36413122015-08-28 11:05:40 -0700297 action="store_true",
298 default=False,
Han Shen43494292015-09-14 10:26:40 -0700299 help="Pass --noschedv2 to crosperf.")
Han Shen36413122015-08-28 11:05:40 -0700300
cmtice46093e52014-12-09 14:59:16 -0800301 options, _ = parser.parse_args(argv)
302 if not options.board:
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800303 print("Please give a board.")
cmtice46093e52014-12-09 14:59:16 -0800304 return 1
305 if not options.remote:
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800306 print("Please give at least one remote machine.")
cmtice46093e52014-12-09 14:59:16 -0800307 return 1
308 if not options.chromeos_root:
Yunlian Jiang14cf5962015-12-11 15:50:14 -0800309 print("Please specify the ChromeOS root directory.")
cmtice46093e52014-12-09 14:59:16 -0800310 return 1
Yunlian Jiang76259e62015-08-21 08:44:31 -0700311 if options.patches:
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700312 patches = options.patches
313 else:
314 patches = USE_NEXT_GCC_PATCH
Yunlian Jiange52838c2015-08-20 14:32:37 -0700315
cmtice46093e52014-12-09 14:59:16 -0800316 fc = ToolchainComparator(options.board, options.remote,
Han Shen36413122015-08-28 11:05:40 -0700317 options.chromeos_root, options.weekday, patches,
Han Shen43494292015-09-14 10:26:40 -0700318 options.noschedv2)
cmtice46093e52014-12-09 14:59:16 -0800319 return fc.DoAll()
320
321
322if __name__ == "__main__":
323 retval = Main(sys.argv)
324 sys.exit(retval)