blob: a663150b96cb275ebf549a99b04a2680078ad1da [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
Yunlian Jiang3c6e4672015-08-24 15:58:22 -070041 def __init__(self, board, remotes, chromeos_root, weekday, patches):
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)
51
cmtice46093e52014-12-09 14:59:16 -080052 if not weekday:
53 self._weekday = time.strftime("%a")
54 else:
55 self._weekday = weekday
cmtice7f3190b2015-05-22 14:14:51 -070056 timestamp = datetime.datetime.strftime(datetime.datetime.now(),
57 "%Y-%m-%d_%H:%M:%S")
58 self._reports_dir = os.path.join(
59 os.path.expanduser("~/nightly_test_reports"),
60 "%s.%s" % (timestamp, board),
61 )
cmtice46093e52014-12-09 14:59:16 -080062
63 def _ParseVanillaImage(self, trybot_image):
64 """
65 Parse a trybot artifact name to get corresponding vanilla image.
66
67 This function takes an artifact name, such as
68 'trybot-daisy-release/R40-6394.0.0-b1389', and returns the
69 corresponding official build name, e.g. 'daisy-release/R40-6394.0.0'.
70 """
71 start_pos = trybot_image.find(self._build)
72 end_pos = trybot_image.rfind("-b")
73 vanilla_image = trybot_image[start_pos:end_pos]
74 return vanilla_image
75
cmtice46093e52014-12-09 14:59:16 -080076 def _FinishSetup(self):
77 """
78 Make sure testing_rsa file is properly set up.
79 """
80 # Fix protections on ssh key
81 command = ("chmod 600 /var/cache/chromeos-cache/distfiles/target"
82 "/chrome-src-internal/src/third_party/chromite/ssh_keys"
83 "/testing_rsa")
84 ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
cmtice7f3190b2015-05-22 14:14:51 -070085 if ret_val != 0:
86 raise RuntimeError("chmod for testing_rsa failed")
cmtice46093e52014-12-09 14:59:16 -080087
88 def _TestImages(self, trybot_image, vanilla_image):
89 """
90 Create crosperf experiment file.
91
92 Given the names of the trybot and vanilla images, create the
93 appropriate crosperf experiment file and launch crosperf on it.
94 """
95 experiment_file_dir = os.path.join (self._chromeos_root, "..",
96 self._weekday)
97 experiment_file_name = "%s_toolchain_experiment.txt" % self._board
98 experiment_file = os.path.join (experiment_file_dir,
99 experiment_file_name)
100 experiment_header = """
101 board: %s
102 remote: %s
Luis Lozanoe1efeb82015-06-16 16:35:44 -0700103 retries: 1
cmtice46093e52014-12-09 14:59:16 -0800104 """ % (self._board, self._remotes)
105 experiment_tests = """
cmtice0c84ea72015-06-25 14:22:36 -0700106 benchmark: all_toolchain_perf {
cmtice46093e52014-12-09 14:59:16 -0800107 suite: telemetry_Crosperf
108 iterations: 3
109 }
110 """
111 with open(experiment_file, "w") as f:
112 print >> f, experiment_header
113 print >> f, experiment_tests
114
115 # Now add vanilla to test file.
116 official_image = """
117 vanilla_image {
118 chromeos_root: %s
119 build: %s
120 }
121 """ % (self._chromeos_root, vanilla_image)
122 print >> f, official_image
123
124 experiment_image = """
125 test_image {
126 chromeos_root: %s
127 build: %s
128 }
129 """ % (self._chromeos_root, trybot_image)
130 print >> f, experiment_image
131
132 crosperf = os.path.join(TOOLCHAIN_DIR,
133 "crosperf",
134 "crosperf")
cmtice9db7ae52015-06-23 10:34:39 -0700135 command = ("%s --no_email=True --results_dir=%s %s" %
cmticeaa700b02015-06-12 13:26:47 -0700136 (crosperf, self._reports_dir, experiment_file))
137
cmtice46093e52014-12-09 14:59:16 -0800138 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700139 if ret != 0:
140 raise RuntimeError("Couldn't run crosperf!")
141 return
cmtice46093e52014-12-09 14:59:16 -0800142
143 def _CopyWeeklyReportFiles(self, trybot_image, vanilla_image):
144 """
145 Put files in place for running seven-day reports.
146
147 Create tar files of the custom and official images and copy them
148 to the weekly reports directory, so they exist when the weekly report
149 gets generated. IMPORTANT NOTE: This function must run *after*
150 crosperf has been run; otherwise the vanilla images will not be there.
151 """
152
153 dry_run = False
154 if (os.getlogin() != ROLE_ACCOUNT):
155 self._l.LogOutput("Running this from non-role account; not copying "
156 "tar files for weekly reports.")
157 dry_run = True
158
159 images_path = os.path.join(os.path.realpath(self._chromeos_root),
160 "chroot/tmp")
161
162 data_dir = os.path.join(WEEKLY_REPORTS_ROOT, self._board)
163 dest_dir = os.path.join (data_dir, self._weekday)
164 if not os.path.exists(dest_dir):
165 os.makedirs(dest_dir)
166
167 # Make sure dest_dir is empty (clean out last week's data).
168 cmd = "cd %s; rm -Rf %s_*_image*" % (dest_dir, self._weekday)
169 if dry_run:
170 print "CMD: %s" % cmd
171 else:
172 self._ce.RunCommand(cmd)
173
174 # Now create new tar files and copy them over.
175 labels = [ "test", "vanilla" ]
176 for label_name in labels:
177 if label_name == "test":
178 test_path = trybot_image
179 else:
180 test_path = vanilla_image
181 tar_file_name = "%s_%s_image.tar" % (self._weekday, label_name)
Han Shenfe054f12015-02-18 15:00:13 -0800182 cmd = ("cd %s; tar -cvf %s %s/chromiumos_test_image.bin; "
183 "cp %s %s/.") % (images_path,
184 tar_file_name,
185 test_path,
186 tar_file_name,
187 dest_dir)
cmtice46093e52014-12-09 14:59:16 -0800188 if dry_run:
189 print "CMD: %s" % cmd
190 tar_ret = 0
191 else:
192 tar_ret = self._ce.RunCommand(cmd)
193 if tar_ret:
194 self._l.LogOutput("Error while creating/copying test tar file(%s)."
195 % tar_file_name)
196
cmtice7f3190b2015-05-22 14:14:51 -0700197 def _SendEmail(self):
198 """Find email message generated by crosperf and send it."""
199 filename = os.path.join(self._reports_dir,
200 "msg_body.html")
201 if (os.path.exists(filename) and
202 os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
203 command = ('cat %s | %s -s "buildbot test results, %s" -team -html'
204 % (filename, MAIL_PROGRAM, self._board))
205 self._ce.RunCommand(command)
cmtice46093e52014-12-09 14:59:16 -0800206
207 def DoAll(self):
208 """
209 Main function inside ToolchainComparator class.
210
211 Launch trybot, get image names, create crosperf experiment file, run
212 crosperf, and copy images into seven-day report directories.
213 """
cmticece5ffa42015-02-12 15:18:43 -0800214 date_str = datetime.date.today()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700215 description = "master_%s_%s_%s" % (self._patches_string,
Han Shenfe054f12015-02-18 15:00:13 -0800216 self._build,
217 date_str)
cmtice46093e52014-12-09 14:59:16 -0800218 trybot_image = buildbot_utils.GetTrybotImage(self._chromeos_root,
219 self._build,
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700220 self._patches,
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700221 description,
222 build_toolchain=True)
cmtice46093e52014-12-09 14:59:16 -0800223
224 vanilla_image = self._ParseVanillaImage(trybot_image)
225
226 print ("trybot_image: %s" % trybot_image)
227 print ("vanilla_image: %s" % vanilla_image)
cmticed54f9802015-02-05 11:04:11 -0800228 if len(trybot_image) == 0:
229 self._l.LogError("Unable to find trybot_image for %s!" % description)
230 return 1
231 if len(vanilla_image) == 0:
232 self._l.LogError("Unable to find vanilla image for %s!" % description)
233 return 1
cmtice46093e52014-12-09 14:59:16 -0800234 if os.getlogin() == ROLE_ACCOUNT:
235 self._FinishSetup()
236
cmtice7f3190b2015-05-22 14:14:51 -0700237 self._TestImages(trybot_image, vanilla_image)
238 self._SendEmail()
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700239 if (self._patches_string == USE_NEXT_GCC_PATCH and
240 self._board in WEEKLY_REPORT_BOARDS):
241 # Only try to copy the image files if the test runs ran successfully.
242 self._CopyWeeklyReportFiles(trybot_image, vanilla_image)
cmtice46093e52014-12-09 14:59:16 -0800243 return 0
244
245
246def Main(argv):
247 """The main function."""
248
249 # Common initializations
250 command_executer.InitCommandExecuter()
251 parser = optparse.OptionParser()
252 parser.add_option("--remote",
253 dest="remote",
254 help="Remote machines to run tests on.")
255 parser.add_option("--board",
256 dest="board",
257 default="x86-zgb",
258 help="The target board.")
259 parser.add_option("--chromeos_root",
260 dest="chromeos_root",
261 help="The chromeos root from which to run tests.")
262 parser.add_option("--weekday", default="",
263 dest="weekday",
264 help="The day of the week for which to run tests.")
Yunlian Jiange52838c2015-08-20 14:32:37 -0700265 parser.add_option("--patch",
266 dest="patches",
267 help="The patches to use for the testing, "
268 "seprate the patch numbers with ',' "
269 "for more than one patches.")
cmtice46093e52014-12-09 14:59:16 -0800270 options, _ = parser.parse_args(argv)
271 if not options.board:
272 print "Please give a board."
273 return 1
274 if not options.remote:
275 print "Please give at least one remote machine."
276 return 1
277 if not options.chromeos_root:
278 print "Please specify the ChromeOS root directory."
279 return 1
Yunlian Jiang76259e62015-08-21 08:44:31 -0700280 if options.patches:
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700281 patches = options.patches
282 else:
283 patches = USE_NEXT_GCC_PATCH
Yunlian Jiange52838c2015-08-20 14:32:37 -0700284
cmtice46093e52014-12-09 14:59:16 -0800285 fc = ToolchainComparator(options.board, options.remote,
Yunlian Jiang3c6e4672015-08-24 15:58:22 -0700286 options.chromeos_root, options.weekday, patches)
cmtice46093e52014-12-09 14:59:16 -0800287 return fc.DoAll()
288
289
290if __name__ == "__main__":
291 retval = Main(sys.argv)
292 sys.exit(retval)