blob: 94788da87b4e59ee3c3c1c929c5ab2d93b42fe61 [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
Caroline Ticeebbc3da2015-09-03 10:27:20 -070034CROSTC_ROOT = "/usr/local/google/crostc"
cmtice46093e52014-12-09 14:59:16 -080035ROLE_ACCOUNT = "mobiletc-prebuild"
36TOOLCHAIN_DIR = os.path.dirname(os.path.realpath(__file__))
cmtice7f3190b2015-05-22 14:14:51 -070037MAIL_PROGRAM = "~/var/bin/mail-sheriff"
Caroline Ticeebbc3da2015-09-03 10:27:20 -070038WEEKLY_REPORTS_ROOT = os.path.join(CROSTC_ROOT, "weekly_test_data")
39PENDING_ARCHIVES_DIR = os.path.join(CROSTC_ROOT, "pending_archives")
40NIGHTLY_TESTS_DIR = os.path.join(CROSTC_ROOT, "nightly_test_reports")
cmtice46093e52014-12-09 14:59:16 -080041
42class ToolchainComparator():
43 """
44 Class for doing the nightly tests work.
45 """
46
Han Shen43494292015-09-14 10:26:40 -070047 def __init__(self, board, remotes, chromeos_root, weekday, 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,
cmtice7f3190b2015-05-22 14:14:51 -070066 "%s.%s" % (timestamp, board),
67 )
cmtice46093e52014-12-09 14:59:16 -080068
69 def _ParseVanillaImage(self, trybot_image):
70 """
71 Parse a trybot artifact name to get corresponding vanilla image.
72
73 This function takes an artifact name, such as
74 'trybot-daisy-release/R40-6394.0.0-b1389', and returns the
75 corresponding official build name, e.g. 'daisy-release/R40-6394.0.0'.
76 """
77 start_pos = trybot_image.find(self._build)
78 end_pos = trybot_image.rfind("-b")
79 vanilla_image = trybot_image[start_pos:end_pos]
80 return vanilla_image
81
cmtice46093e52014-12-09 14:59:16 -080082 def _FinishSetup(self):
83 """
84 Make sure testing_rsa file is properly set up.
85 """
86 # Fix protections on ssh key
87 command = ("chmod 600 /var/cache/chromeos-cache/distfiles/target"
88 "/chrome-src-internal/src/third_party/chromite/ssh_keys"
89 "/testing_rsa")
90 ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
cmtice7f3190b2015-05-22 14:14:51 -070091 if ret_val != 0:
92 raise RuntimeError("chmod for testing_rsa failed")
cmtice46093e52014-12-09 14:59:16 -080093
94 def _TestImages(self, trybot_image, vanilla_image):
95 """
96 Create crosperf experiment file.
97
98 Given the names of the trybot and vanilla images, create the
99 appropriate crosperf experiment file and launch crosperf on it.
100 """
101 experiment_file_dir = os.path.join (self._chromeos_root, "..",
102 self._weekday)
103 experiment_file_name = "%s_toolchain_experiment.txt" % self._board
Yunlian Jiang2f563562015-08-28 13:54:04 -0700104
105 if self._patches_string == USE_LLVM_PATCH:
106 experiment_file_name = "%s_llvm_experiment.txt" % self._board
107
cmtice46093e52014-12-09 14:59:16 -0800108 experiment_file = os.path.join (experiment_file_dir,
109 experiment_file_name)
110 experiment_header = """
111 board: %s
112 remote: %s
Luis Lozanoe1efeb82015-06-16 16:35:44 -0700113 retries: 1
cmtice46093e52014-12-09 14:59:16 -0800114 """ % (self._board, self._remotes)
115 experiment_tests = """
cmtice0c84ea72015-06-25 14:22:36 -0700116 benchmark: all_toolchain_perf {
cmtice46093e52014-12-09 14:59:16 -0800117 suite: telemetry_Crosperf
118 iterations: 3
119 }
120 """
121 with open(experiment_file, "w") as f:
122 print >> f, experiment_header
123 print >> f, experiment_tests
124
125 # Now add vanilla to test file.
126 official_image = """
127 vanilla_image {
128 chromeos_root: %s
129 build: %s
130 }
131 """ % (self._chromeos_root, vanilla_image)
132 print >> f, official_image
133
134 experiment_image = """
135 test_image {
136 chromeos_root: %s
137 build: %s
138 }
139 """ % (self._chromeos_root, trybot_image)
140 print >> f, experiment_image
141
142 crosperf = os.path.join(TOOLCHAIN_DIR,
143 "crosperf",
144 "crosperf")
Han Shen43494292015-09-14 10:26:40 -0700145 noschedv2_opts = '--noschedv2' if self._noschedv2 else ''
Han Shen36413122015-08-28 11:05:40 -0700146 command = ("{crosperf} --no_email=True --results_dir={r_dir} "
Han Shen43494292015-09-14 10:26:40 -0700147 "--json_report=True {noschedv2_opts} {exp_file}").format(
Han Shen36413122015-08-28 11:05:40 -0700148 crosperf=crosperf,
149 r_dir=self._reports_dir,
Han Shen43494292015-09-14 10:26:40 -0700150 noschedv2_opts=noschedv2_opts,
Han Shen36413122015-08-28 11:05:40 -0700151 exp_file=experiment_file)
cmticeaa700b02015-06-12 13:26:47 -0700152
cmtice46093e52014-12-09 14:59:16 -0800153 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700154 if ret != 0:
155 raise RuntimeError("Couldn't run crosperf!")
Caroline Ticeebbc3da2015-09-03 10:27:20 -0700156 else:
157 # Copy json report to pending archives directory.
158 command = "cp %s/*.json %s/." % (self._reports_dir, PENDING_ARCHIVES_DIR)
159 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700160 return
cmtice46093e52014-12-09 14:59:16 -0800161
162 def _CopyWeeklyReportFiles(self, trybot_image, vanilla_image):
163 """
164 Put files in place for running seven-day reports.
165
166 Create tar files of the custom and official images and copy them
167 to the weekly reports directory, so they exist when the weekly report
168 gets generated. IMPORTANT NOTE: This function must run *after*
169 crosperf has been run; otherwise the vanilla images will not be there.
170 """
171
172 dry_run = False
173 if (os.getlogin() != ROLE_ACCOUNT):
174 self._l.LogOutput("Running this from non-role account; not copying "
175 "tar files for weekly reports.")
176 dry_run = True
177
178 images_path = os.path.join(os.path.realpath(self._chromeos_root),
179 "chroot/tmp")
180
181 data_dir = os.path.join(WEEKLY_REPORTS_ROOT, self._board)
182 dest_dir = os.path.join (data_dir, self._weekday)
183 if not os.path.exists(dest_dir):
184 os.makedirs(dest_dir)
185
186 # Make sure dest_dir is empty (clean out last week's data).
187 cmd = "cd %s; rm -Rf %s_*_image*" % (dest_dir, self._weekday)
188 if dry_run:
189 print "CMD: %s" % cmd
190 else:
191 self._ce.RunCommand(cmd)
192
193 # Now create new tar files and copy them over.
194 labels = [ "test", "vanilla" ]
195 for label_name in labels:
196 if label_name == "test":
197 test_path = trybot_image
198 else:
199 test_path = vanilla_image
200 tar_file_name = "%s_%s_image.tar" % (self._weekday, label_name)
Han Shenfe054f12015-02-18 15:00:13 -0800201 cmd = ("cd %s; tar -cvf %s %s/chromiumos_test_image.bin; "
202 "cp %s %s/.") % (images_path,
203 tar_file_name,
204 test_path,
205 tar_file_name,
206 dest_dir)
cmtice46093e52014-12-09 14:59:16 -0800207 if dry_run:
208 print "CMD: %s" % cmd
209 tar_ret = 0
210 else:
211 tar_ret = self._ce.RunCommand(cmd)
212 if tar_ret:
213 self._l.LogOutput("Error while creating/copying test tar file(%s)."
214 % tar_file_name)
215
cmtice7f3190b2015-05-22 14:14:51 -0700216 def _SendEmail(self):
217 """Find email message generated by crosperf and send it."""
218 filename = os.path.join(self._reports_dir,
219 "msg_body.html")
220 if (os.path.exists(filename) and
221 os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
Yunlian Jiang2f563562015-08-28 13:54:04 -0700222 email_title = "buildbot test results"
223 if self._patches_string == USE_LLVM_PATCH:
224 email_title = "buildbot llvm test results"
225 command = ('cat %s | %s -s "%s, %s" -team -html'
226 % (filename, MAIL_PROGRAM, email_title, self._board))
cmtice7f3190b2015-05-22 14:14:51 -0700227 self._ce.RunCommand(command)
cmtice46093e52014-12-09 14:59:16 -0800228
229 def DoAll(self):
230 """
231 Main function inside ToolchainComparator class.
232
233 Launch trybot, get image names, create crosperf experiment file, run
234 crosperf, and copy images into seven-day report directories.
235 """
cmticece5ffa42015-02-12 15:18:43 -0800236 date_str = datetime.date.today()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700237 description = "master_%s_%s_%s" % (self._patches_string,
Han Shenfe054f12015-02-18 15:00:13 -0800238 self._build,
239 date_str)
cmtice46093e52014-12-09 14:59:16 -0800240 trybot_image = buildbot_utils.GetTrybotImage(self._chromeos_root,
241 self._build,
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700242 self._patches,
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700243 description,
244 build_toolchain=True)
cmtice46093e52014-12-09 14:59:16 -0800245
246 vanilla_image = self._ParseVanillaImage(trybot_image)
247
248 print ("trybot_image: %s" % trybot_image)
249 print ("vanilla_image: %s" % vanilla_image)
cmticed54f9802015-02-05 11:04:11 -0800250 if len(trybot_image) == 0:
251 self._l.LogError("Unable to find trybot_image for %s!" % description)
252 return 1
253 if len(vanilla_image) == 0:
254 self._l.LogError("Unable to find vanilla image for %s!" % description)
255 return 1
cmtice46093e52014-12-09 14:59:16 -0800256 if os.getlogin() == ROLE_ACCOUNT:
257 self._FinishSetup()
258
cmtice7f3190b2015-05-22 14:14:51 -0700259 self._TestImages(trybot_image, vanilla_image)
260 self._SendEmail()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700261 if (self._patches_string == USE_NEXT_GCC_PATCH and
262 self._board in WEEKLY_REPORT_BOARDS):
263 # Only try to copy the image files if the test runs ran successfully.
264 self._CopyWeeklyReportFiles(trybot_image, vanilla_image)
cmtice46093e52014-12-09 14:59:16 -0800265 return 0
266
267
268def Main(argv):
269 """The main function."""
270
271 # Common initializations
272 command_executer.InitCommandExecuter()
273 parser = optparse.OptionParser()
274 parser.add_option("--remote",
275 dest="remote",
276 help="Remote machines to run tests on.")
277 parser.add_option("--board",
278 dest="board",
279 default="x86-zgb",
280 help="The target board.")
281 parser.add_option("--chromeos_root",
282 dest="chromeos_root",
283 help="The chromeos root from which to run tests.")
284 parser.add_option("--weekday", default="",
285 dest="weekday",
286 help="The day of the week for which to run tests.")
Yunlian Jiange52838c2015-08-20 14:32:37 -0700287 parser.add_option("--patch",
288 dest="patches",
289 help="The patches to use for the testing, "
290 "seprate the patch numbers with ',' "
291 "for more than one patches.")
Han Shen43494292015-09-14 10:26:40 -0700292 parser.add_option("--noschedv2",
293 dest="noschedv2",
Han Shen36413122015-08-28 11:05:40 -0700294 action="store_true",
295 default=False,
Han Shen43494292015-09-14 10:26:40 -0700296 help="Pass --noschedv2 to crosperf.")
Han Shen36413122015-08-28 11:05:40 -0700297
cmtice46093e52014-12-09 14:59:16 -0800298 options, _ = parser.parse_args(argv)
299 if not options.board:
300 print "Please give a board."
301 return 1
302 if not options.remote:
303 print "Please give at least one remote machine."
304 return 1
305 if not options.chromeos_root:
306 print "Please specify the ChromeOS root directory."
307 return 1
Yunlian Jiang76259e62015-08-21 08:44:31 -0700308 if options.patches:
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700309 patches = options.patches
310 else:
311 patches = USE_NEXT_GCC_PATCH
Yunlian Jiange52838c2015-08-20 14:32:37 -0700312
cmtice46093e52014-12-09 14:59:16 -0800313 fc = ToolchainComparator(options.board, options.remote,
Han Shen36413122015-08-28 11:05:40 -0700314 options.chromeos_root, options.weekday, patches,
Han Shen43494292015-09-14 10:26:40 -0700315 options.noschedv2)
cmtice46093e52014-12-09 14:59:16 -0800316 return fc.DoAll()
317
318
319if __name__ == "__main__":
320 retval = Main(sys.argv)
321 sys.exit(retval)