blob: c899758f484a15edc3810d1a5a4c6373c0e21f37 [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
28# The boards on which we run weekly reports
29WEEKLY_REPORT_BOARDS = ["lumpy"]
cmtice46093e52014-12-09 14:59:16 -080030
31WEEKLY_REPORTS_ROOT = "/usr/local/google/crostc/weekly_test_data"
32ROLE_ACCOUNT = "mobiletc-prebuild"
33TOOLCHAIN_DIR = os.path.dirname(os.path.realpath(__file__))
cmtice7f3190b2015-05-22 14:14:51 -070034MAIL_PROGRAM = "~/var/bin/mail-sheriff"
cmtice46093e52014-12-09 14:59:16 -080035
36class ToolchainComparator():
37 """
38 Class for doing the nightly tests work.
39 """
40
Han Shen36413122015-08-28 11:05:40 -070041 def __init__(self, board, remotes, chromeos_root, weekday, patches, schedv2=False):
cmtice46093e52014-12-09 14:59:16 -080042 self._board = board
43 self._remotes = remotes
44 self._chromeos_root = chromeos_root
45 self._base_dir = os.getcwd()
46 self._ce = command_executer.GetCommandExecuter()
47 self._l = logger.GetLogger()
48 self._build = "%s-release" % board
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070049 self._patches = patches.split(',')
50 self._patches_string = '_'.join(str(p) for p in self._patches)
Han Shen36413122015-08-28 11:05:40 -070051 self._schedv2 = schedv2
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070052
cmtice46093e52014-12-09 14:59:16 -080053 if not weekday:
54 self._weekday = time.strftime("%a")
55 else:
56 self._weekday = weekday
cmtice7f3190b2015-05-22 14:14:51 -070057 timestamp = datetime.datetime.strftime(datetime.datetime.now(),
58 "%Y-%m-%d_%H:%M:%S")
59 self._reports_dir = os.path.join(
60 os.path.expanduser("~/nightly_test_reports"),
61 "%s.%s" % (timestamp, board),
62 )
cmtice46093e52014-12-09 14:59:16 -080063
64 def _ParseVanillaImage(self, trybot_image):
65 """
66 Parse a trybot artifact name to get corresponding vanilla image.
67
68 This function takes an artifact name, such as
69 'trybot-daisy-release/R40-6394.0.0-b1389', and returns the
70 corresponding official build name, e.g. 'daisy-release/R40-6394.0.0'.
71 """
72 start_pos = trybot_image.find(self._build)
73 end_pos = trybot_image.rfind("-b")
74 vanilla_image = trybot_image[start_pos:end_pos]
75 return vanilla_image
76
cmtice46093e52014-12-09 14:59:16 -080077 def _FinishSetup(self):
78 """
79 Make sure testing_rsa file is properly set up.
80 """
81 # Fix protections on ssh key
82 command = ("chmod 600 /var/cache/chromeos-cache/distfiles/target"
83 "/chrome-src-internal/src/third_party/chromite/ssh_keys"
84 "/testing_rsa")
85 ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
cmtice7f3190b2015-05-22 14:14:51 -070086 if ret_val != 0:
87 raise RuntimeError("chmod for testing_rsa failed")
cmtice46093e52014-12-09 14:59:16 -080088
89 def _TestImages(self, trybot_image, vanilla_image):
90 """
91 Create crosperf experiment file.
92
93 Given the names of the trybot and vanilla images, create the
94 appropriate crosperf experiment file and launch crosperf on it.
95 """
96 experiment_file_dir = os.path.join (self._chromeos_root, "..",
97 self._weekday)
98 experiment_file_name = "%s_toolchain_experiment.txt" % self._board
99 experiment_file = os.path.join (experiment_file_dir,
100 experiment_file_name)
101 experiment_header = """
102 board: %s
103 remote: %s
Luis Lozanoe1efeb82015-06-16 16:35:44 -0700104 retries: 1
cmtice46093e52014-12-09 14:59:16 -0800105 """ % (self._board, self._remotes)
106 experiment_tests = """
cmtice0c84ea72015-06-25 14:22:36 -0700107 benchmark: all_toolchain_perf {
cmtice46093e52014-12-09 14:59:16 -0800108 suite: telemetry_Crosperf
109 iterations: 3
110 }
111 """
112 with open(experiment_file, "w") as f:
113 print >> f, experiment_header
114 print >> f, experiment_tests
115
116 # Now add vanilla to test file.
117 official_image = """
118 vanilla_image {
119 chromeos_root: %s
120 build: %s
121 }
122 """ % (self._chromeos_root, vanilla_image)
123 print >> f, official_image
124
125 experiment_image = """
126 test_image {
127 chromeos_root: %s
128 build: %s
129 }
130 """ % (self._chromeos_root, trybot_image)
131 print >> f, experiment_image
132
133 crosperf = os.path.join(TOOLCHAIN_DIR,
134 "crosperf",
135 "crosperf")
Han Shen36413122015-08-28 11:05:40 -0700136 schedv2_opts = '--schedv2 --logging_level=verbose' if self._schedv2 else ''
137 command = ("{crosperf} --no_email=True --results_dir={r_dir} "
138 "{schedv2_opts} {exp_file}").format(
139 crosperf=crosperf,
140 r_dir=self._reports_dir,
141 schedv2_opts=schedv2_opts,
142 exp_file=experiment_file)
cmticeaa700b02015-06-12 13:26:47 -0700143
cmtice46093e52014-12-09 14:59:16 -0800144 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700145 if ret != 0:
146 raise RuntimeError("Couldn't run crosperf!")
147 return
cmtice46093e52014-12-09 14:59:16 -0800148
149 def _CopyWeeklyReportFiles(self, trybot_image, vanilla_image):
150 """
151 Put files in place for running seven-day reports.
152
153 Create tar files of the custom and official images and copy them
154 to the weekly reports directory, so they exist when the weekly report
155 gets generated. IMPORTANT NOTE: This function must run *after*
156 crosperf has been run; otherwise the vanilla images will not be there.
157 """
158
159 dry_run = False
160 if (os.getlogin() != ROLE_ACCOUNT):
161 self._l.LogOutput("Running this from non-role account; not copying "
162 "tar files for weekly reports.")
163 dry_run = True
164
165 images_path = os.path.join(os.path.realpath(self._chromeos_root),
166 "chroot/tmp")
167
168 data_dir = os.path.join(WEEKLY_REPORTS_ROOT, self._board)
169 dest_dir = os.path.join (data_dir, self._weekday)
170 if not os.path.exists(dest_dir):
171 os.makedirs(dest_dir)
172
173 # Make sure dest_dir is empty (clean out last week's data).
174 cmd = "cd %s; rm -Rf %s_*_image*" % (dest_dir, self._weekday)
175 if dry_run:
176 print "CMD: %s" % cmd
177 else:
178 self._ce.RunCommand(cmd)
179
180 # Now create new tar files and copy them over.
181 labels = [ "test", "vanilla" ]
182 for label_name in labels:
183 if label_name == "test":
184 test_path = trybot_image
185 else:
186 test_path = vanilla_image
187 tar_file_name = "%s_%s_image.tar" % (self._weekday, label_name)
Han Shenfe054f12015-02-18 15:00:13 -0800188 cmd = ("cd %s; tar -cvf %s %s/chromiumos_test_image.bin; "
189 "cp %s %s/.") % (images_path,
190 tar_file_name,
191 test_path,
192 tar_file_name,
193 dest_dir)
cmtice46093e52014-12-09 14:59:16 -0800194 if dry_run:
195 print "CMD: %s" % cmd
196 tar_ret = 0
197 else:
198 tar_ret = self._ce.RunCommand(cmd)
199 if tar_ret:
200 self._l.LogOutput("Error while creating/copying test tar file(%s)."
201 % tar_file_name)
202
cmtice7f3190b2015-05-22 14:14:51 -0700203 def _SendEmail(self):
204 """Find email message generated by crosperf and send it."""
205 filename = os.path.join(self._reports_dir,
206 "msg_body.html")
207 if (os.path.exists(filename) and
208 os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
209 command = ('cat %s | %s -s "buildbot test results, %s" -team -html'
210 % (filename, MAIL_PROGRAM, self._board))
211 self._ce.RunCommand(command)
cmtice46093e52014-12-09 14:59:16 -0800212
213 def DoAll(self):
214 """
215 Main function inside ToolchainComparator class.
216
217 Launch trybot, get image names, create crosperf experiment file, run
218 crosperf, and copy images into seven-day report directories.
219 """
cmticece5ffa42015-02-12 15:18:43 -0800220 date_str = datetime.date.today()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700221 description = "master_%s_%s_%s" % (self._patches_string,
Han Shenfe054f12015-02-18 15:00:13 -0800222 self._build,
223 date_str)
cmtice46093e52014-12-09 14:59:16 -0800224 trybot_image = buildbot_utils.GetTrybotImage(self._chromeos_root,
225 self._build,
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700226 self._patches,
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700227 description,
228 build_toolchain=True)
cmtice46093e52014-12-09 14:59:16 -0800229
230 vanilla_image = self._ParseVanillaImage(trybot_image)
231
232 print ("trybot_image: %s" % trybot_image)
233 print ("vanilla_image: %s" % vanilla_image)
cmticed54f9802015-02-05 11:04:11 -0800234 if len(trybot_image) == 0:
235 self._l.LogError("Unable to find trybot_image for %s!" % description)
236 return 1
237 if len(vanilla_image) == 0:
238 self._l.LogError("Unable to find vanilla image for %s!" % description)
239 return 1
cmtice46093e52014-12-09 14:59:16 -0800240 if os.getlogin() == ROLE_ACCOUNT:
241 self._FinishSetup()
242
cmtice7f3190b2015-05-22 14:14:51 -0700243 self._TestImages(trybot_image, vanilla_image)
244 self._SendEmail()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700245 if (self._patches_string == USE_NEXT_GCC_PATCH and
246 self._board in WEEKLY_REPORT_BOARDS):
247 # Only try to copy the image files if the test runs ran successfully.
248 self._CopyWeeklyReportFiles(trybot_image, vanilla_image)
cmtice46093e52014-12-09 14:59:16 -0800249 return 0
250
251
252def Main(argv):
253 """The main function."""
254
255 # Common initializations
256 command_executer.InitCommandExecuter()
257 parser = optparse.OptionParser()
258 parser.add_option("--remote",
259 dest="remote",
260 help="Remote machines to run tests on.")
261 parser.add_option("--board",
262 dest="board",
263 default="x86-zgb",
264 help="The target board.")
265 parser.add_option("--chromeos_root",
266 dest="chromeos_root",
267 help="The chromeos root from which to run tests.")
268 parser.add_option("--weekday", default="",
269 dest="weekday",
270 help="The day of the week for which to run tests.")
Yunlian Jiange52838c2015-08-20 14:32:37 -0700271 parser.add_option("--patch",
272 dest="patches",
273 help="The patches to use for the testing, "
274 "seprate the patch numbers with ',' "
275 "for more than one patches.")
Han Shen36413122015-08-28 11:05:40 -0700276 parser.add_option("--schedv2",
277 dest="schedv2",
278 action="store_true",
279 default=False,
280 help="Pass --schedv2 to crosperf.")
281
cmtice46093e52014-12-09 14:59:16 -0800282 options, _ = parser.parse_args(argv)
283 if not options.board:
284 print "Please give a board."
285 return 1
286 if not options.remote:
287 print "Please give at least one remote machine."
288 return 1
289 if not options.chromeos_root:
290 print "Please specify the ChromeOS root directory."
291 return 1
Yunlian Jiang76259e62015-08-21 08:44:31 -0700292 if options.patches:
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700293 patches = options.patches
294 else:
295 patches = USE_NEXT_GCC_PATCH
Yunlian Jiange52838c2015-08-20 14:32:37 -0700296
cmtice46093e52014-12-09 14:59:16 -0800297 fc = ToolchainComparator(options.board, options.remote,
Han Shen36413122015-08-28 11:05:40 -0700298 options.chromeos_root, options.weekday, patches,
299 options.schedv2)
cmtice46093e52014-12-09 14:59:16 -0800300 return fc.DoAll()
301
302
303if __name__ == "__main__":
304 retval = Main(sys.argv)
305 sys.exit(retval)