blob: 8e4cf2d2aea8d0bf72f1cf75037b7527ff690c63 [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 Jiange52838c2015-08-20 14:32:37 -070026USE_NEXT_GCC_PATCH = [230260]
cmtice46093e52014-12-09 14:59:16 -080027
28WEEKLY_REPORTS_ROOT = "/usr/local/google/crostc/weekly_test_data"
29ROLE_ACCOUNT = "mobiletc-prebuild"
30TOOLCHAIN_DIR = os.path.dirname(os.path.realpath(__file__))
cmtice7f3190b2015-05-22 14:14:51 -070031MAIL_PROGRAM = "~/var/bin/mail-sheriff"
cmtice46093e52014-12-09 14:59:16 -080032
33class ToolchainComparator():
34 """
35 Class for doing the nightly tests work.
36 """
37
38 def __init__(self, board, remotes, chromeos_root, weekday):
39 self._board = board
40 self._remotes = remotes
41 self._chromeos_root = chromeos_root
42 self._base_dir = os.getcwd()
43 self._ce = command_executer.GetCommandExecuter()
44 self._l = logger.GetLogger()
45 self._build = "%s-release" % board
46 if not weekday:
47 self._weekday = time.strftime("%a")
48 else:
49 self._weekday = weekday
cmtice7f3190b2015-05-22 14:14:51 -070050 timestamp = datetime.datetime.strftime(datetime.datetime.now(),
51 "%Y-%m-%d_%H:%M:%S")
52 self._reports_dir = os.path.join(
53 os.path.expanduser("~/nightly_test_reports"),
54 "%s.%s" % (timestamp, board),
55 )
cmtice46093e52014-12-09 14:59:16 -080056
57 def _ParseVanillaImage(self, trybot_image):
58 """
59 Parse a trybot artifact name to get corresponding vanilla image.
60
61 This function takes an artifact name, such as
62 'trybot-daisy-release/R40-6394.0.0-b1389', and returns the
63 corresponding official build name, e.g. 'daisy-release/R40-6394.0.0'.
64 """
65 start_pos = trybot_image.find(self._build)
66 end_pos = trybot_image.rfind("-b")
67 vanilla_image = trybot_image[start_pos:end_pos]
68 return vanilla_image
69
cmtice46093e52014-12-09 14:59:16 -080070 def _FinishSetup(self):
71 """
72 Make sure testing_rsa file is properly set up.
73 """
74 # Fix protections on ssh key
75 command = ("chmod 600 /var/cache/chromeos-cache/distfiles/target"
76 "/chrome-src-internal/src/third_party/chromite/ssh_keys"
77 "/testing_rsa")
78 ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
cmtice7f3190b2015-05-22 14:14:51 -070079 if ret_val != 0:
80 raise RuntimeError("chmod for testing_rsa failed")
cmtice46093e52014-12-09 14:59:16 -080081
82 def _TestImages(self, trybot_image, vanilla_image):
83 """
84 Create crosperf experiment file.
85
86 Given the names of the trybot and vanilla images, create the
87 appropriate crosperf experiment file and launch crosperf on it.
88 """
89 experiment_file_dir = os.path.join (self._chromeos_root, "..",
90 self._weekday)
91 experiment_file_name = "%s_toolchain_experiment.txt" % self._board
92 experiment_file = os.path.join (experiment_file_dir,
93 experiment_file_name)
94 experiment_header = """
95 board: %s
96 remote: %s
Luis Lozanoe1efeb82015-06-16 16:35:44 -070097 retries: 1
cmtice46093e52014-12-09 14:59:16 -080098 """ % (self._board, self._remotes)
99 experiment_tests = """
cmtice0c84ea72015-06-25 14:22:36 -0700100 benchmark: all_toolchain_perf {
cmtice46093e52014-12-09 14:59:16 -0800101 suite: telemetry_Crosperf
102 iterations: 3
103 }
104 """
105 with open(experiment_file, "w") as f:
106 print >> f, experiment_header
107 print >> f, experiment_tests
108
109 # Now add vanilla to test file.
110 official_image = """
111 vanilla_image {
112 chromeos_root: %s
113 build: %s
114 }
115 """ % (self._chromeos_root, vanilla_image)
116 print >> f, official_image
117
118 experiment_image = """
119 test_image {
120 chromeos_root: %s
121 build: %s
122 }
123 """ % (self._chromeos_root, trybot_image)
124 print >> f, experiment_image
125
126 crosperf = os.path.join(TOOLCHAIN_DIR,
127 "crosperf",
128 "crosperf")
cmtice9db7ae52015-06-23 10:34:39 -0700129 command = ("%s --no_email=True --results_dir=%s %s" %
cmticeaa700b02015-06-12 13:26:47 -0700130 (crosperf, self._reports_dir, experiment_file))
131
cmtice46093e52014-12-09 14:59:16 -0800132 ret = self._ce.RunCommand(command)
cmtice7f3190b2015-05-22 14:14:51 -0700133 if ret != 0:
134 raise RuntimeError("Couldn't run crosperf!")
135 return
cmtice46093e52014-12-09 14:59:16 -0800136
137 def _CopyWeeklyReportFiles(self, trybot_image, vanilla_image):
138 """
139 Put files in place for running seven-day reports.
140
141 Create tar files of the custom and official images and copy them
142 to the weekly reports directory, so they exist when the weekly report
143 gets generated. IMPORTANT NOTE: This function must run *after*
144 crosperf has been run; otherwise the vanilla images will not be there.
145 """
146
147 dry_run = False
148 if (os.getlogin() != ROLE_ACCOUNT):
149 self._l.LogOutput("Running this from non-role account; not copying "
150 "tar files for weekly reports.")
151 dry_run = True
152
153 images_path = os.path.join(os.path.realpath(self._chromeos_root),
154 "chroot/tmp")
155
156 data_dir = os.path.join(WEEKLY_REPORTS_ROOT, self._board)
157 dest_dir = os.path.join (data_dir, self._weekday)
158 if not os.path.exists(dest_dir):
159 os.makedirs(dest_dir)
160
161 # Make sure dest_dir is empty (clean out last week's data).
162 cmd = "cd %s; rm -Rf %s_*_image*" % (dest_dir, self._weekday)
163 if dry_run:
164 print "CMD: %s" % cmd
165 else:
166 self._ce.RunCommand(cmd)
167
168 # Now create new tar files and copy them over.
169 labels = [ "test", "vanilla" ]
170 for label_name in labels:
171 if label_name == "test":
172 test_path = trybot_image
173 else:
174 test_path = vanilla_image
175 tar_file_name = "%s_%s_image.tar" % (self._weekday, label_name)
Han Shenfe054f12015-02-18 15:00:13 -0800176 cmd = ("cd %s; tar -cvf %s %s/chromiumos_test_image.bin; "
177 "cp %s %s/.") % (images_path,
178 tar_file_name,
179 test_path,
180 tar_file_name,
181 dest_dir)
cmtice46093e52014-12-09 14:59:16 -0800182 if dry_run:
183 print "CMD: %s" % cmd
184 tar_ret = 0
185 else:
186 tar_ret = self._ce.RunCommand(cmd)
187 if tar_ret:
188 self._l.LogOutput("Error while creating/copying test tar file(%s)."
189 % tar_file_name)
190
cmtice7f3190b2015-05-22 14:14:51 -0700191 def _SendEmail(self):
192 """Find email message generated by crosperf and send it."""
193 filename = os.path.join(self._reports_dir,
194 "msg_body.html")
195 if (os.path.exists(filename) and
196 os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
197 command = ('cat %s | %s -s "buildbot test results, %s" -team -html'
198 % (filename, MAIL_PROGRAM, self._board))
199 self._ce.RunCommand(command)
cmtice46093e52014-12-09 14:59:16 -0800200
201 def DoAll(self):
202 """
203 Main function inside ToolchainComparator class.
204
205 Launch trybot, get image names, create crosperf experiment file, run
206 crosperf, and copy images into seven-day report directories.
207 """
cmticece5ffa42015-02-12 15:18:43 -0800208 date_str = datetime.date.today()
Yunlian Jiang76259e62015-08-21 08:44:31 -0700209 patch_string = '_'.join(str(p) for p in USE_NEXT_GCC_PATCH)
210 description = "master_%s_%s_%s" % (patch_string,
Han Shenfe054f12015-02-18 15:00:13 -0800211 self._build,
212 date_str)
cmtice46093e52014-12-09 14:59:16 -0800213 trybot_image = buildbot_utils.GetTrybotImage(self._chromeos_root,
214 self._build,
Yunlian Jiange52838c2015-08-20 14:32:37 -0700215 USE_NEXT_GCC_PATCH,
Luis Lozano8a68b2d2015-04-23 14:37:09 -0700216 description,
217 build_toolchain=True)
cmtice46093e52014-12-09 14:59:16 -0800218
219 vanilla_image = self._ParseVanillaImage(trybot_image)
220
221 print ("trybot_image: %s" % trybot_image)
222 print ("vanilla_image: %s" % vanilla_image)
cmticed54f9802015-02-05 11:04:11 -0800223 if len(trybot_image) == 0:
224 self._l.LogError("Unable to find trybot_image for %s!" % description)
225 return 1
226 if len(vanilla_image) == 0:
227 self._l.LogError("Unable to find vanilla image for %s!" % description)
228 return 1
cmtice46093e52014-12-09 14:59:16 -0800229 if os.getlogin() == ROLE_ACCOUNT:
230 self._FinishSetup()
231
cmtice7f3190b2015-05-22 14:14:51 -0700232 self._TestImages(trybot_image, vanilla_image)
233 self._SendEmail()
234 # Only try to copy the image files if the test runs ran successfully.
235 self._CopyWeeklyReportFiles(trybot_image, vanilla_image)
cmtice46093e52014-12-09 14:59:16 -0800236 return 0
237
238
239def Main(argv):
240 """The main function."""
241
242 # Common initializations
243 command_executer.InitCommandExecuter()
244 parser = optparse.OptionParser()
245 parser.add_option("--remote",
246 dest="remote",
247 help="Remote machines to run tests on.")
248 parser.add_option("--board",
249 dest="board",
250 default="x86-zgb",
251 help="The target board.")
252 parser.add_option("--chromeos_root",
253 dest="chromeos_root",
254 help="The chromeos root from which to run tests.")
255 parser.add_option("--weekday", default="",
256 dest="weekday",
257 help="The day of the week for which to run tests.")
Yunlian Jiange52838c2015-08-20 14:32:37 -0700258 parser.add_option("--patch",
259 dest="patches",
260 help="The patches to use for the testing, "
261 "seprate the patch numbers with ',' "
262 "for more than one patches.")
cmtice46093e52014-12-09 14:59:16 -0800263 options, _ = parser.parse_args(argv)
264 if not options.board:
265 print "Please give a board."
266 return 1
267 if not options.remote:
268 print "Please give at least one remote machine."
269 return 1
270 if not options.chromeos_root:
271 print "Please specify the ChromeOS root directory."
272 return 1
273
Yunlian Jiang76259e62015-08-21 08:44:31 -0700274 if options.patches:
275 global USE_NEXT_GCC_PATCH
Yunlian Jiangbb04def2015-08-24 09:17:02 -0700276 USE_NEXT_GCC_PATCH = options.patches.split(',')
Yunlian Jiange52838c2015-08-20 14:32:37 -0700277
cmtice46093e52014-12-09 14:59:16 -0800278 fc = ToolchainComparator(options.board, options.remote,
279 options.chromeos_root, options.weekday)
280 return fc.DoAll()
281
282
283if __name__ == "__main__":
284 retval = Main(sys.argv)
285 sys.exit(retval)