| #!/usr/bin/python |
| # |
| # Copyright 2010 Google Inc. All Rights Reserved. |
| |
| """Script adapter used by automation client for testing dejagnu. |
| This is not intended to be run on command line. |
| To kick off a single dejagnu run, use chromeos/v14/dejagnu/run_dejagnu.py |
| """ |
| |
| __author__ = 'shenhan@google.com (Han Shen)' |
| |
| import optparse |
| import os |
| from os import path |
| import sys |
| import setup_chromeos |
| import build_tc |
| |
| from dejagnu import run_dejagnu |
| from utils import command_executer |
| from utils import email_sender |
| |
| class DejagnuAdapter(object): |
| |
| # TODO(shenhan): move these to constants.py. |
| _CHROMIUM_GCC_GIT = ("https://chromium.googlesource.com/" |
| "chromiumos/third_party/gcc.git") |
| _CHROMIUM_GCC_BRANCH = "gcc.gnu.org/branches/google/gcc-4_7-mobile" |
| |
| _cmd_exec = command_executer.GetCommandExecuter() |
| |
| def __init__(self, board, remote, gcc_dir, |
| chromeos_root, runtestflags, cleanup): |
| self._board = board |
| self._remote = remote |
| self._gcc_dir = gcc_dir |
| self._chromeos_root = chromeos_root |
| self._runtestflags = runtestflags |
| self._cleanup = cleanup |
| |
| def SetupChromeOS(self): |
| cmd = [setup_chromeos.__file__, |
| "--dir=" + self._chromeos_root, "--minilayout", "--jobs=8"] |
| ret = setup_chromeos.Main(cmd) |
| if ret: |
| raise Exception("Failed to checkout chromeos") |
| ## Do cros_sdk and setup_board, otherwise build_tc in next step will fail. |
| cmd = "cd {0} && cros_sdk --download".format(self._chromeos_root) |
| ret = self._cmd_exec.RunCommand(cmd, terminated_timeout=9000) |
| if ret: |
| raise Exception("Failed to create chroot.") |
| |
| def SetupBoard(self): |
| cmd = "./setup_board --board=" + self._board |
| ret = self._cmd_exec.ChrootRunCommand(self._chromeos_root, |
| cmd, terminated_timeout=4000) |
| if ret: |
| raise Exception("Failed to setup board.") |
| |
| def CheckoutGCC(self): |
| cmd = "git clone {0} {1} && cd {1} && git checkout {2}".format( |
| self._CHROMIUM_GCC_GIT, self._gcc_dir, self._CHROMIUM_GCC_BRANCH) |
| |
| ret = self._cmd_exec.RunCommand(cmd, terminated_timeout=300) |
| if ret: |
| raise Exception("Failed to checkout gcc.") |
| ## Handle build_tc bug. |
| cmd = ("touch {0}/gcc/config/arm/arm-tune.md " + \ |
| "{0}/gcc/config/arm/arm-tables.opt").format(self._gcc_dir) |
| ret = self._cmd_exec.RunCommand(cmd) |
| |
| def BuildGCC(self): |
| build_gcc_args = [build_tc.__file__, |
| "--board=" + self._board, |
| "--chromeos_root=" + self._chromeos_root, |
| "--gcc_dir=" + self._gcc_dir] |
| ret = build_tc.Main(build_gcc_args) |
| if ret: |
| raise Exception("Building gcc failed.") |
| |
| def CheckGCC(self): |
| args = [run_dejagnu.__file__, |
| "--board=" + self._board, |
| "--chromeos_root=" + self._chromeos_root, |
| "--mount=" + self._gcc_dir, |
| "--remote=" + self._remote] |
| if self._cleanup: |
| args.append("--cleanup=" + self._cleanup) |
| if self._runtestflags: |
| args.append("--flags=" + self._runtestflags) |
| return run_dejagnu.Main(args) |
| |
| |
| # Parse the output log to determine how many failures we have. |
| # Return -1 if parse output log failed. |
| def GetNumNewFailures(str): |
| if not str: |
| return 0 |
| start_counting = False |
| n_failures = 0 |
| for l in str.splitlines(): |
| print l |
| if not start_counting and 'Build results not in the manifest' in l: |
| start_counting = True |
| elif start_counting and l and ( |
| l.find('UNRESOLVED:') == 0 or l.find('FAIL:') == 0 or \ |
| l.find('XFAIL:') == 0 or l.find('XPASS:') == 0): |
| n_failures = n_failures + 1 |
| if not start_counting: |
| return -1 |
| return n_failures |
| |
| # Do not throw any exception in this function! |
| def EmailResult(result): |
| email_to = ['c-compiler-chrome@google.com'] |
| email_from = ['dejagnu-job@google.com'] |
| if len(result) == 4: |
| subject = 'Job failed: dejagnu test didn\'t finish' |
| email_text = 'Job failed prematurely, check exception below.\n' + \ |
| result[3] |
| elif result[0]: |
| subject = 'Job finished: dejagnu test failed' |
| num_new_failures = GetNumNewFailures(result[1]) |
| if num_new_failures >= 0: |
| summary = '{0} new fail(s), check log below.'.format(num_new_failures) |
| else: |
| summary = 'At least 1 new fail found, check log below.' |
| email_text = summary + \ |
| ('\nStdout ====\n' |
| '{0}\n' |
| '\nStderr ===\n' |
| '{1}\n').format(result[1], result[2]) |
| else: |
| subject = 'Job finished: dejagnu test passed' |
| email_text = ('Cool! No new fail found.\n' |
| '\nStdout ====\n' |
| '{0}\n' |
| '\nStderr ====\n' |
| '{1}\n').format(result[1], result[2]) |
| |
| try: |
| email_sender.EmailSender().SendEmail(email_to, subject, email_text) |
| print 'Email sent.' |
| except Exception as e: |
| # Do not propagate this email sending exception, you want to email an |
| # email exception? Just log it on console. |
| print ('Sending email failed - {0}' |
| 'Subject: {1}' |
| 'Text: {2}').format( |
| str(e), subject, email_text) |
| |
| |
| def ProcessArguments(argv): |
| """Processing script arguments.""" |
| parser = optparse.OptionParser(description=( |
| 'This script is used by nightly client to test gcc. ' |
| 'DO NOT run it unless you know what you are doing.'), |
| usage='test_gcc_dejagnu.py options') |
| parser.add_option('-b', '--board', dest='board', |
| help=('Required. Specify board type. For example ' |
| '\'lumpy\' and \'daisy\'')) |
| parser.add_option('-r', '--remote', dest='remote', |
| help=('Required. Specify remote board address')) |
| parser.add_option('-g', '--gcc_dir', dest='gcc_dir', default='gcc.live', |
| help=('Optional. Specify gcc checkout directory.')) |
| parser.add_option('-c', '--chromeos_root', dest='chromeos_root', |
| default='chromeos.live', |
| help=('Optional. Specify chromeos checkout directory.')) |
| parser.add_option('--cleanup', dest='cleanup', default=None, |
| help=('Optional. Do cleanup after the test.')) |
| parser.add_option('--runtestflags', dest='runtestflags', default=None, |
| help=('Optional. Options to RUNTESTFLAGS env var ' |
| 'while invoking make check. ' |
| '(Mainly used for testing purpose.)')) |
| |
| options, args = parser.parse_args(argv) |
| |
| if not options.board or not options.remote: |
| raise Exception("--board and --remote are mandatory options.") |
| |
| return options |
| |
| |
| def Main(argv): |
| opt = ProcessArguments(argv) |
| adapter = DejagnuAdapter( |
| opt.board, opt.remote, opt.gcc_dir, opt.chromeos_root, |
| opt.runtestflags, opt.cleanup) |
| try: |
| adapter.SetupChromeOS() |
| adapter.SetupBoard() |
| adapter.CheckoutGCC() |
| adapter.BuildGCC() |
| ret = adapter.CheckGCC() |
| except Exception as e: |
| print e |
| ret = (1, '', '', str(e)) |
| finally: |
| EmailResult(ret) |
| return ret |
| |
| |
| if __name__ == "__main__": |
| retval = Main(sys.argv) |
| sys.exit(retval[0]) |