aboutsummaryrefslogtreecommitdiff
path: root/buildbot_test_toolchains.py
diff options
context:
space:
mode:
Diffstat (limited to 'buildbot_test_toolchains.py')
-rwxr-xr-xbuildbot_test_toolchains.py356
1 files changed, 356 insertions, 0 deletions
diff --git a/buildbot_test_toolchains.py b/buildbot_test_toolchains.py
new file mode 100755
index 00000000..5bef28a4
--- /dev/null
+++ b/buildbot_test_toolchains.py
@@ -0,0 +1,356 @@
+#!/usr/bin/env python2
+#
+# Copyright 2016 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Script for running nightly compiler tests on ChromeOS.
+
+This script launches a buildbot to build ChromeOS with the latest compiler on
+a particular board; then it finds and downloads the trybot image and the
+corresponding official image, and runs crosperf performance tests comparing
+the two. It then generates a report, emails it to the c-compiler-chrome, as
+well as copying the images into the seven-day reports directory.
+"""
+
+# Script to test different toolchains against ChromeOS benchmarks.
+
+from __future__ import print_function
+
+import argparse
+import datetime
+import os
+import re
+import sys
+import time
+
+from cros_utils import command_executer
+from cros_utils import logger
+
+from cros_utils import buildbot_utils
+
+# CL that updated GCC ebuilds to use 'next_gcc'.
+USE_NEXT_GCC_PATCH = '230260'
+
+# CL that uses LLVM to build the peppy image.
+USE_LLVM_PATCH = '295217'
+
+# CL that uses LLVM-Next to build the images (includes chrome).
+USE_LLVM_NEXT_PATCH = '424123'
+
+CROSTC_ROOT = '/usr/local/google/crostc'
+ROLE_ACCOUNT = 'mobiletc-prebuild'
+TOOLCHAIN_DIR = os.path.dirname(os.path.realpath(__file__))
+MAIL_PROGRAM = '~/var/bin/mail-sheriff'
+PENDING_ARCHIVES_DIR = os.path.join(CROSTC_ROOT, 'pending_archives')
+NIGHTLY_TESTS_DIR = os.path.join(CROSTC_ROOT, 'nightly_test_reports')
+
+IMAGE_DIR = '{board}-{image_type}'
+IMAGE_VERSION_STR = r'{chrome_version}-{tip}\.{branch}\.{branch_branch}'
+IMAGE_FS = IMAGE_DIR + '/' + IMAGE_VERSION_STR
+TRYBOT_IMAGE_FS = 'trybot-' + IMAGE_FS + '-{build_id}'
+PFQ_IMAGE_FS = IMAGE_FS + '-rc1'
+IMAGE_RE_GROUPS = {
+ 'board': r'(?P<board>\S+)',
+ 'image_type': r'(?P<image_type>\S+)',
+ 'chrome_version': r'(?P<chrome_version>R\d+)',
+ 'tip': r'(?P<tip>\d+)',
+ 'branch': r'(?P<branch>\d+)',
+ 'branch_branch': r'(?P<branch_branch>\d+)',
+ 'build_id': r'(?P<build_id>b\d+)'
+}
+TRYBOT_IMAGE_RE = TRYBOT_IMAGE_FS.format(**IMAGE_RE_GROUPS)
+
+
+class ToolchainComparator(object):
+ """Class for doing the nightly tests work."""
+
+ def __init__(self,
+ board,
+ remotes,
+ chromeos_root,
+ weekday,
+ patches,
+ noschedv2=False):
+ self._board = board
+ self._remotes = remotes
+ self._chromeos_root = chromeos_root
+ self._base_dir = os.getcwd()
+ self._ce = command_executer.GetCommandExecuter()
+ self._l = logger.GetLogger()
+ self._build = '%s-release' % board
+ self._patches = patches.split(',')
+ self._patches_string = '_'.join(str(p) for p in self._patches)
+ self._noschedv2 = noschedv2
+
+ if not weekday:
+ self._weekday = time.strftime('%a')
+ else:
+ self._weekday = weekday
+ timestamp = datetime.datetime.strftime(datetime.datetime.now(),
+ '%Y-%m-%d_%H:%M:%S')
+ self._reports_dir = os.path.join(
+ NIGHTLY_TESTS_DIR,
+ '%s.%s' % (timestamp, board),)
+
+ def _GetVanillaImageName(self, trybot_image):
+ """Given a trybot artifact name, get latest vanilla image name.
+
+ Args:
+ trybot_image: artifact name such as
+ 'trybot-daisy-release/R40-6394.0.0-b1389'
+
+ Returns:
+ Latest official image name, e.g. 'daisy-release/R57-9089.0.0'.
+ """
+ mo = re.search(TRYBOT_IMAGE_RE, trybot_image)
+ assert mo
+ dirname = IMAGE_DIR.replace('\\', '').format(**mo.groupdict())
+ version = buildbot_utils.GetGSContent(self._chromeos_root,
+ dirname + '/LATEST-master')
+ return dirname + '/' + version
+
+ def _GetNonAFDOImageName(self, trybot_image):
+ """Given a trybot artifact name, get corresponding non-AFDO image name.
+
+ We get the non-AFDO image from the PFQ builders. This image
+ is not generated for all the boards and, the closest PFQ image
+ was the one build for the previous ChromeOS version (the chrome
+ used in the current version is the one validated in the previous
+ version).
+ The previous ChromeOS does not always exist either. So, we try
+ a couple of versions before.
+
+ Args:
+ trybot_image: artifact name such as
+ 'trybot-daisy-release/R40-6394.0.0-b1389'
+
+ Returns:
+ Corresponding chrome PFQ image name, e.g.
+ 'daisy-chrome-pfq/R40-6393.0.0-rc1'.
+ """
+ mo = re.search(TRYBOT_IMAGE_RE, trybot_image)
+ assert mo
+ image_dict = mo.groupdict()
+ image_dict['image_type'] = 'chrome-pfq'
+ for _ in xrange(2):
+ image_dict['tip'] = str(int(image_dict['tip']) - 1)
+ nonafdo_image = PFQ_IMAGE_FS.replace('\\', '').format(**image_dict)
+ if buildbot_utils.DoesImageExist(self._chromeos_root, nonafdo_image):
+ return nonafdo_image
+ return ''
+
+ def _FinishSetup(self):
+ """Make sure testing_rsa file is properly set up."""
+ # Fix protections on ssh key
+ command = ('chmod 600 /var/cache/chromeos-cache/distfiles/target'
+ '/chrome-src-internal/src/third_party/chromite/ssh_keys'
+ '/testing_rsa')
+ ret_val = self._ce.ChrootRunCommand(self._chromeos_root, command)
+ if ret_val != 0:
+ raise RuntimeError('chmod for testing_rsa failed')
+
+ def _TestImages(self, trybot_image, vanilla_image, nonafdo_image):
+ """Create crosperf experiment file.
+
+ Given the names of the trybot, vanilla and non-AFDO images, create the
+ appropriate crosperf experiment file and launch crosperf on it.
+ """
+ experiment_file_dir = os.path.join(self._chromeos_root, '..', self._weekday)
+ experiment_file_name = '%s_toolchain_experiment.txt' % self._board
+
+ compiler_string = 'gcc'
+ if USE_LLVM_NEXT_PATCH in self._patches_string:
+ experiment_file_name = '%s_llvm_next_experiment.txt' % self._board
+ compiler_string = 'llvm_next'
+ elif USE_LLVM_PATCH in self._patches_string:
+ experiment_file_name = '%s_llvm_experiment.txt' % self._board
+ compiler_string = 'llvm'
+
+ experiment_file = os.path.join(experiment_file_dir, experiment_file_name)
+ experiment_header = """
+ board: %s
+ remote: %s
+ retries: 1
+ """ % (self._board, self._remotes)
+ experiment_tests = """
+ benchmark: all_toolchain_perf {
+ suite: telemetry_Crosperf
+ iterations: 3
+ }
+
+ benchmark: page_cycler_v2.typical_25 {
+ suite: telemetry_Crosperf
+ iterations: 2
+ run_local: False
+ retries: 0
+ }
+ """
+
+ with open(experiment_file, 'w') as f:
+ f.write(experiment_header)
+ f.write(experiment_tests)
+
+ # Now add vanilla to test file.
+ official_image = """
+ vanilla_image {
+ chromeos_root: %s
+ build: %s
+ compiler: gcc
+ }
+ """ % (self._chromeos_root, vanilla_image)
+ f.write(official_image)
+
+ # Now add non-AFDO image to test file.
+ if nonafdo_image:
+ official_nonafdo_image = """
+ nonafdo_image {
+ chromeos_root: %s
+ build: %s
+ compiler: gcc
+ }
+ """ % (self._chromeos_root, nonafdo_image)
+ f.write(official_nonafdo_image)
+
+ label_string = '%s_trybot_image' % compiler_string
+ if USE_NEXT_GCC_PATCH in self._patches:
+ label_string = 'gcc_next_trybot_image'
+
+ # Reuse autotest files from vanilla image for trybot images
+ autotest_files = os.path.join('/tmp', vanilla_image, 'autotest_files')
+ experiment_image = """
+ %s {
+ chromeos_root: %s
+ build: %s
+ autotest_path: %s
+ compiler: %s
+ }
+ """ % (label_string, self._chromeos_root, trybot_image,
+ autotest_files, compiler_string)
+ f.write(experiment_image)
+
+ crosperf = os.path.join(TOOLCHAIN_DIR, 'crosperf', 'crosperf')
+ noschedv2_opts = '--noschedv2' if self._noschedv2 else ''
+ command = ('{crosperf} --no_email=True --results_dir={r_dir} '
+ '--json_report=True {noschedv2_opts} {exp_file}').format(
+ crosperf=crosperf,
+ r_dir=self._reports_dir,
+ noschedv2_opts=noschedv2_opts,
+ exp_file=experiment_file)
+
+ ret = self._ce.RunCommand(command)
+ if ret != 0:
+ raise RuntimeError('Crosperf execution error!')
+ else:
+ # Copy json report to pending archives directory.
+ command = 'cp %s/*.json %s/.' % (self._reports_dir, PENDING_ARCHIVES_DIR)
+ ret = self._ce.RunCommand(command)
+ return
+
+ def _SendEmail(self):
+ """Find email message generated by crosperf and send it."""
+ filename = os.path.join(self._reports_dir, 'msg_body.html')
+ if (os.path.exists(filename) and
+ os.path.exists(os.path.expanduser(MAIL_PROGRAM))):
+ email_title = 'buildbot test results'
+ if USE_LLVM_NEXT_PATCH in self._patches_string:
+ email_title = 'buildbot llvm_next test results'
+ elif USE_LLVM_PATCH in self._patches_string:
+ email_title = 'buildbot llvm test results'
+ command = ('cat %s | %s -s "%s, %s" -team -html' %
+ (filename, MAIL_PROGRAM, email_title, self._board))
+ self._ce.RunCommand(command)
+
+ def DoAll(self):
+ """Main function inside ToolchainComparator class.
+
+ Launch trybot, get image names, create crosperf experiment file, run
+ crosperf, and copy images into seven-day report directories.
+ """
+ date_str = datetime.date.today()
+ description = 'master_%s_%s_%s' % (self._patches_string, self._build,
+ date_str)
+ build_id, trybot_image = buildbot_utils.GetTrybotImage(
+ self._chromeos_root,
+ self._build,
+ self._patches,
+ description,
+ other_flags=['--notests'],
+ build_toolchain=True)
+
+ print('trybot_url: \
+ https://uberchromegw.corp.google.com/i/chromiumos.tryserver/builders/release/builds/%s'
+ % build_id)
+ if len(trybot_image) == 0:
+ self._l.LogError('Unable to find trybot_image for %s!' % description)
+ return 1
+
+ vanilla_image = self._GetVanillaImageName(trybot_image)
+ nonafdo_image = self._GetNonAFDOImageName(trybot_image)
+
+ print('trybot_image: %s' % trybot_image)
+ print('vanilla_image: %s' % vanilla_image)
+ print('nonafdo_image: %s' % nonafdo_image)
+
+ if os.getlogin() == ROLE_ACCOUNT:
+ self._FinishSetup()
+
+ self._TestImages(trybot_image, vanilla_image, nonafdo_image)
+ self._SendEmail()
+ return 0
+
+
+def Main(argv):
+ """The main function."""
+
+ # Common initializations
+ command_executer.InitCommandExecuter()
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--remote', dest='remote', help='Remote machines to run tests on.')
+ parser.add_argument(
+ '--board', dest='board', default='x86-zgb', help='The target board.')
+ parser.add_argument(
+ '--chromeos_root',
+ dest='chromeos_root',
+ help='The chromeos root from which to run tests.')
+ parser.add_argument(
+ '--weekday',
+ default='',
+ dest='weekday',
+ help='The day of the week for which to run tests.')
+ parser.add_argument(
+ '--patch',
+ dest='patches',
+ help='The patches to use for the testing, '
+ "seprate the patch numbers with ',' "
+ 'for more than one patches.')
+ parser.add_argument(
+ '--noschedv2',
+ dest='noschedv2',
+ action='store_true',
+ default=False,
+ help='Pass --noschedv2 to crosperf.')
+
+ options = parser.parse_args(argv[1:])
+ if not options.board:
+ print('Please give a board.')
+ return 1
+ if not options.remote:
+ print('Please give at least one remote machine.')
+ return 1
+ if not options.chromeos_root:
+ print('Please specify the ChromeOS root directory.')
+ return 1
+ if options.patches:
+ patches = options.patches
+ else:
+ patches = USE_NEXT_GCC_PATCH
+
+ fc = ToolchainComparator(options.board, options.remote, options.chromeos_root,
+ options.weekday, patches, options.noschedv2)
+ return fc.DoAll()
+
+
+if __name__ == '__main__':
+ retval = Main(sys.argv)
+ sys.exit(retval)