blob: d931c9081780f691c4158fba4deb1c71441be190 [file] [log] [blame]
cmtice46093e52014-12-09 14:59:16 -08001#!/usr/bin/python
2"""
3Script for running nightly compiler tests on ChromeOS.
4
5This script launches a buildbot to build ChromeOS with the latest compiler on
6a particular board; then it finds and downloads the trybot image and the
7corresponding official image, and runs crosperf performance tests comparing
8the two. It then generates a report, emails it to the c-compiler-chrome, as
9well as copying the images into the seven-day reports directory.
10"""
11
12# Script to test different toolchains against ChromeOS benchmarks.
cmticece5ffa42015-02-12 15:18:43 -080013import datetime
cmtice46093e52014-12-09 14:59:16 -080014import optparse
15import os
16import sys
17import time
18import urllib2
19
20from utils import command_executer
21from utils import logger
22
23from utils import buildbot_utils
24
25# CL that updated GCC ebuilds to use 'next_gcc'.
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070026USE_NEXT_GCC_PATCH = "230260"
27
Yunlian Jiang2f563562015-08-28 13:54:04 -070028# CL that uses LLVM to build the peppy image.
29USE_LLVM_PATCH = "295217"
30
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070031# The boards on which we run weekly reports
32WEEKLY_REPORT_BOARDS = ["lumpy"]
cmtice46093e52014-12-09 14:59:16 -080033
34WEEKLY_REPORTS_ROOT = "/usr/local/google/crostc/weekly_test_data"
35ROLE_ACCOUNT = "mobiletc-prebuild"
36TOOLCHAIN_DIR = os.path.dirname(os.path.realpath(__file__))
cmtice7f3190b2015-05-22 14:14:51 -070037MAIL_PROGRAM = "~/var/bin/mail-sheriff"
cmtice46093e52014-12-09 14:59:16 -080038
39class ToolchainComparator():
40 """
41 Class for doing the nightly tests work.
42 """
43
Han Shen36413122015-08-28 11:05:40 -070044 def __init__(self, board, remotes, chromeos_root, weekday, patches, schedv2=False):
cmtice46093e52014-12-09 14:59:16 -080045 self._board = board
46 self._remotes = remotes
47 self._chromeos_root = chromeos_root
48 self._base_dir = os.getcwd()
49 self._ce = command_executer.GetCommandExecuter()
50 self._l = logger.GetLogger()
51 self._build = "%s-release" % board
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070052 self._patches = patches.split(',')
53 self._patches_string = '_'.join(str(p) for p in self._patches)
Han Shen36413122015-08-28 11:05:40 -070054 self._schedv2 = schedv2
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070055
cmtice46093e52014-12-09 14:59:16 -080056 if not weekday:
57 self._weekday = time.strftime("%a")
58 else:
59 self._weekday = weekday
cmtice7f3190b2015-05-22 14:14:51 -070060 timestamp = datetime.datetime.strftime(datetime.datetime.now(),
61 "%Y-%m-%d_%H:%M:%S")
62 self._reports_dir = os.path.join(
63 os.path.expanduser("~/nightly_test_reports"),
64 "%s.%s" % (timestamp, board),
65 )
cmtice46093e52014-12-09 14:59:16 -080066
67 def _ParseVanillaImage(self, trybot_image):
68 """
69 Parse a trybot artifact name to get corresponding vanilla image.
70
71 This function takes an artifact name, such as
72 'trybot-daisy-release/R40-6394.0.0-b1389', and returns the
73 corresponding official build name, e.g. 'daisy-release/R40-6394.0.0'.
74 """
75 start_pos = trybot_image.find(self._build)
76 end_pos = trybot_image.rfind("-b")
77 vanilla_image = trybot_image[start_pos:end_pos]
78 return vanilla_image
79
cmtice46093e52014-12-09 14:59:16 -080080 def _FinishSetup(self):
81 """
82 Make sure testing_rsa file is properly set up.
83 """
84 # Fix protections on ssh key
85 command = ("chmod 600 /var/cache/chromeos-cache/distfiles/target"
86 "/chrome-src-internal/src/third_party/chromite/ssh_keys"
87 "/testing_rsa")
88 ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
cmtice7f3190b2015-05-22 14:14:51 -070089 if ret_val != 0:
90 raise RuntimeError("chmod for testing_rsa failed")
cmtice46093e52014-12-09 14:59:16 -080091
92 def _TestImages(self, trybot_image, vanilla_image):
93 """
94 Create crosperf experiment file.
95
96 Given the names of the trybot and vanilla images, create the
97 appropriate crosperf experiment file and launch crosperf on it.
98 """
99 experiment_file_dir = os.path.join (self._chromeos_root, "..",
100 self._weekday)
101 experiment_file_name = "%s_toolchain_experiment.txt" % self._board
Yunlian Jiang2f563562015-08-28 13:54:04 -0700102
103 if self._patches_string == USE_LLVM_PATCH:
104 experiment_file_name = "%s_llvm_experiment.txt" % self._board
105
cmtice46093e52014-12-09 14:59:16 -0800106 experiment_file = os.path.join (experiment_file_dir,
107 experiment_file_name)
108 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 = """
cmtice0c84ea72015-06-25 14:22:36 -0700114 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:
120 print >> f, experiment_header
121 print >> f, experiment_tests
122
123 # Now add vanilla to test file.
124 official_image = """
125 vanilla_image {
126 chromeos_root: %s
127 build: %s
128 }
129 """ % (self._chromeos_root, vanilla_image)
130 print >> f, official_image
131
132 experiment_image = """
133 test_image {
134 chromeos_root: %s
135 build: %s
136 }
137 """ % (self._chromeos_root, trybot_image)
138 print >> f, experiment_image
139
140 crosperf = os.path.join(TOOLCHAIN_DIR,
141 "crosperf",
142 "crosperf")
Han Shen36413122015-08-28 11:05:40 -0700143 schedv2_opts = '--schedv2 --logging_level=verbose' if self._schedv2 else ''
144 command = ("{crosperf} --no_email=True --results_dir={r_dir} "
145 "{schedv2_opts} {exp_file}").format(
146 crosperf=crosperf,
147 r_dir=self._reports_dir,
148 schedv2_opts=schedv2_opts,
149 exp_file=experiment_file)
cmticeaa700b02015-06-12 13:26:47 -0700150
cmtice46093e52014-12-09 14:59:16 -0800151 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700152 if ret != 0:
153 raise RuntimeError("Couldn't run crosperf!")
154 return
cmtice46093e52014-12-09 14:59:16 -0800155
156 def _CopyWeeklyReportFiles(self, trybot_image, vanilla_image):
157 """
158 Put files in place for running seven-day reports.
159
160 Create tar files of the custom and official images and copy them
161 to the weekly reports directory, so they exist when the weekly report
162 gets generated. IMPORTANT NOTE: This function must run *after*
163 crosperf has been run; otherwise the vanilla images will not be there.
164 """
165
166 dry_run = False
167 if (os.getlogin() != ROLE_ACCOUNT):
168 self._l.LogOutput("Running this from non-role account; not copying "
169 "tar files for weekly reports.")
170 dry_run = True
171
172 images_path = os.path.join(os.path.realpath(self._chromeos_root),
173 "chroot/tmp")
174
175 data_dir = os.path.join(WEEKLY_REPORTS_ROOT, self._board)
176 dest_dir = os.path.join (data_dir, self._weekday)
177 if not os.path.exists(dest_dir):
178 os.makedirs(dest_dir)
179
180 # Make sure dest_dir is empty (clean out last week's data).
181 cmd = "cd %s; rm -Rf %s_*_image*" % (dest_dir, self._weekday)
182 if dry_run:
183 print "CMD: %s" % cmd
184 else:
185 self._ce.RunCommand(cmd)
186
187 # Now create new tar files and copy them over.
188 labels = [ "test", "vanilla" ]
189 for label_name in labels:
190 if label_name == "test":
191 test_path = trybot_image
192 else:
193 test_path = vanilla_image
194 tar_file_name = "%s_%s_image.tar" % (self._weekday, label_name)
Han Shenfe054f12015-02-18 15:00:13 -0800195 cmd = ("cd %s; tar -cvf %s %s/chromiumos_test_image.bin; "
196 "cp %s %s/.") % (images_path,
197 tar_file_name,
198 test_path,
199 tar_file_name,
200 dest_dir)
cmtice46093e52014-12-09 14:59:16 -0800201 if dry_run:
202 print "CMD: %s" % cmd
203 tar_ret = 0
204 else:
205 tar_ret = self._ce.RunCommand(cmd)
206 if tar_ret:
207 self._l.LogOutput("Error while creating/copying test tar file(%s)."
208 % tar_file_name)
209
cmtice7f3190b2015-05-22 14:14:51 -0700210 def _SendEmail(self):
211 """Find email message generated by crosperf and send it."""
212 filename = os.path.join(self._reports_dir,
213 "msg_body.html")
214 if (os.path.exists(filename) and
215 os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
Yunlian Jiang2f563562015-08-28 13:54:04 -0700216 email_title = "buildbot test results"
217 if self._patches_string == USE_LLVM_PATCH:
218 email_title = "buildbot llvm test results"
219 command = ('cat %s | %s -s "%s, %s" -team -html'
220 % (filename, MAIL_PROGRAM, email_title, self._board))
cmtice7f3190b2015-05-22 14:14:51 -0700221 self._ce.RunCommand(command)
cmtice46093e52014-12-09 14:59:16 -0800222
223 def DoAll(self):
224 """
225 Main function inside ToolchainComparator class.
226
227 Launch trybot, get image names, create crosperf experiment file, run
228 crosperf, and copy images into seven-day report directories.
229 """
cmticece5ffa42015-02-12 15:18:43 -0800230 date_str = datetime.date.today()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700231 description = "master_%s_%s_%s" % (self._patches_string,
Han Shenfe054f12015-02-18 15:00:13 -0800232 self._build,
233 date_str)
cmtice46093e52014-12-09 14:59:16 -0800234 trybot_image = buildbot_utils.GetTrybotImage(self._chromeos_root,
235 self._build,
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700236 self._patches,
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700237 description,
238 build_toolchain=True)
cmtice46093e52014-12-09 14:59:16 -0800239
240 vanilla_image = self._ParseVanillaImage(trybot_image)
241
242 print ("trybot_image: %s" % trybot_image)
243 print ("vanilla_image: %s" % vanilla_image)
cmticed54f9802015-02-05 11:04:11 -0800244 if len(trybot_image) == 0:
245 self._l.LogError("Unable to find trybot_image for %s!" % description)
246 return 1
247 if len(vanilla_image) == 0:
248 self._l.LogError("Unable to find vanilla image for %s!" % description)
249 return 1
cmtice46093e52014-12-09 14:59:16 -0800250 if os.getlogin() == ROLE_ACCOUNT:
251 self._FinishSetup()
252
cmtice7f3190b2015-05-22 14:14:51 -0700253 self._TestImages(trybot_image, vanilla_image)
254 self._SendEmail()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700255 if (self._patches_string == USE_NEXT_GCC_PATCH and
256 self._board in WEEKLY_REPORT_BOARDS):
257 # Only try to copy the image files if the test runs ran successfully.
258 self._CopyWeeklyReportFiles(trybot_image, vanilla_image)
cmtice46093e52014-12-09 14:59:16 -0800259 return 0
260
261
262def Main(argv):
263 """The main function."""
264
265 # Common initializations
266 command_executer.InitCommandExecuter()
267 parser = optparse.OptionParser()
268 parser.add_option("--remote",
269 dest="remote",
270 help="Remote machines to run tests on.")
271 parser.add_option("--board",
272 dest="board",
273 default="x86-zgb",
274 help="The target board.")
275 parser.add_option("--chromeos_root",
276 dest="chromeos_root",
277 help="The chromeos root from which to run tests.")
278 parser.add_option("--weekday", default="",
279 dest="weekday",
280 help="The day of the week for which to run tests.")
Yunlian Jiange52838c2015-08-20 14:32:37 -0700281 parser.add_option("--patch",
282 dest="patches",
283 help="The patches to use for the testing, "
284 "seprate the patch numbers with ',' "
285 "for more than one patches.")
Han Shen36413122015-08-28 11:05:40 -0700286 parser.add_option("--schedv2",
287 dest="schedv2",
288 action="store_true",
289 default=False,
290 help="Pass --schedv2 to crosperf.")
291
cmtice46093e52014-12-09 14:59:16 -0800292 options, _ = parser.parse_args(argv)
293 if not options.board:
294 print "Please give a board."
295 return 1
296 if not options.remote:
297 print "Please give at least one remote machine."
298 return 1
299 if not options.chromeos_root:
300 print "Please specify the ChromeOS root directory."
301 return 1
Yunlian Jiang76259e62015-08-21 08:44:31 -0700302 if options.patches:
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700303 patches = options.patches
304 else:
305 patches = USE_NEXT_GCC_PATCH
Yunlian Jiange52838c2015-08-20 14:32:37 -0700306
cmtice46093e52014-12-09 14:59:16 -0800307 fc = ToolchainComparator(options.board, options.remote,
Han Shen36413122015-08-28 11:05:40 -0700308 options.chromeos_root, options.weekday, patches,
309 options.schedv2)
cmtice46093e52014-12-09 14:59:16 -0800310 return fc.DoAll()
311
312
313if __name__ == "__main__":
314 retval = Main(sys.argv)
315 sys.exit(retval)