1#!/usr/bin/python2 2# 3# Copyright 2010 Google Inc. All Rights Reserved. 4"""Script adapter used by automation client for testing dejagnu. 5 6 This is not intended to be run on command line. 7 To kick off a single dejagnu run, use ./dejagnu/run_dejagnu.py 8""" 9 10from __future__ import print_function 11 12__author__ = 'shenhan@google.com (Han Shen)' 13 14import argparse 15import sys 16import setup_chromeos 17import build_tc 18 19from dejagnu import run_dejagnu 20from cros_utils import command_executer 21from cros_utils import email_sender 22 23 24class DejagnuAdapter(object): 25 """Dejagnu Adapter class""" 26 27 # TODO(shenhan): move these to constants.py. 28 _CHROMIUM_GCC_GIT = ('https://chromium.googlesource.com/' 29 'chromiumos/third_party/gcc.git') 30 _CHROMIUM_GCC_BRANCH = 'gcc.gnu.org/branches/google/gcc-4_7-mobile' 31 32 _cmd_exec = command_executer.GetCommandExecuter() 33 34 def __init__(self, board, remote, gcc_dir, chromeos_root, runtestflags, 35 cleanup): 36 self._board = board 37 self._remote = remote 38 self._gcc_dir = gcc_dir 39 self._chromeos_root = chromeos_root 40 self._runtestflags = runtestflags 41 self._cleanup = cleanup 42 43 def SetupChromeOS(self): 44 cmd = [setup_chromeos.__file__, '--dir=' + self._chromeos_root, 45 '--minilayout', '--jobs=8'] 46 ret = setup_chromeos.Main(cmd) 47 if ret: 48 raise RuntimeError('Failed to checkout chromeos') 49 ## Do cros_sdk and setup_board, otherwise build_tc in next step will fail. 50 cmd = 'cd {0} && cros_sdk --download'.format(self._chromeos_root) 51 ret = self._cmd_exec.RunCommand(cmd, terminated_timeout=9000) 52 if ret: 53 raise RuntimeError('Failed to create chroot.') 54 55 def SetupBoard(self): 56 cmd = './setup_board --board=' + self._board 57 ret = self._cmd_exec.ChrootRunCommand(self._chromeos_root, 58 cmd, 59 terminated_timeout=4000) 60 if ret: 61 raise RuntimeError('Failed to setup board.') 62 63 def CheckoutGCC(self): 64 cmd = 'git clone {0} {1} && cd {1} && git checkout {2}'.format( 65 self._CHROMIUM_GCC_GIT, self._gcc_dir, self._CHROMIUM_GCC_BRANCH) 66 67 ret = self._cmd_exec.RunCommand(cmd, terminated_timeout=300) 68 if ret: 69 raise RuntimeError('Failed to checkout gcc.') 70 ## Handle build_tc bug. 71 cmd = ('touch {0}/gcc/config/arm/arm-tune.md ' + \ 72 '{0}/gcc/config/arm/arm-tables.opt').format(self._gcc_dir) 73 ret = self._cmd_exec.RunCommand(cmd) 74 75 def BuildGCC(self): 76 build_gcc_args = [build_tc.__file__, '--board=' + self._board, 77 '--chromeos_root=' + self._chromeos_root, 78 '--gcc_dir=' + self._gcc_dir] 79 ret = build_tc.Main(build_gcc_args) 80 if ret: 81 raise RuntimeError('Building gcc failed.') 82 83 def CheckGCC(self): 84 args = [run_dejagnu.__file__, '--board=' + self._board, 85 '--chromeos_root=' + self._chromeos_root, 86 '--mount=' + self._gcc_dir, '--remote=' + self._remote] 87 if self._cleanup: 88 args.append('--cleanup=' + self._cleanup) 89 if self._runtestflags: 90 args.append('--flags=' + self._runtestflags) 91 return run_dejagnu.Main(args) 92 93 94# Parse the output log to determine how many failures we have. 95# Return -1 if parse output log failed. 96def GetNumNewFailures(input_str): 97 if not input_str: 98 return 0 99 start_counting = False 100 n_failures = 0 101 for l in input_str.splitlines(): 102 print(l) 103 if not start_counting and 'Build results not in the manifest' in l: 104 start_counting = True 105 elif start_counting and l and ( 106 l.find('UNRESOLVED:') == 0 or l.find('FAIL:') == 0 or 107 l.find('XFAIL:') == 0 or l.find('XPASS:') == 0): 108 n_failures = n_failures + 1 109 if not start_counting: 110 return -1 111 return n_failures 112 113 114# Do not throw any exception in this function! 115def EmailResult(result): 116 email_to = ['c-compiler-chrome@google.com'] 117 if len(result) == 4: 118 subject = 'Job failed: dejagnu test didn\'t finish' 119 email_text = 'Job failed prematurely, check exception below.\n' + \ 120 result[3] 121 elif result[0]: 122 subject = 'Job finished: dejagnu test failed' 123 num_new_failures = GetNumNewFailures(result[1]) 124 if num_new_failures >= 0: 125 summary = '{0} new fail(s), check log below.'.format(num_new_failures) 126 else: 127 summary = 'At least 1 new fail found, check log below.' 128 email_text = summary + \ 129 ('\nStdout ====\n' 130 '{0}\n' 131 '\nStderr ===\n' 132 '{1}\n').format(result[1], result[2]) 133 else: 134 subject = 'Job finished: dejagnu test passed' 135 email_text = ('Cool! No new fail found.\n' 136 '\nStdout ====\n' 137 '{0}\n' 138 '\nStderr ====\n' 139 '{1}\n').format(result[1], result[2]) 140 141 try: 142 email_sender.EmailSender().SendEmail(email_to, subject, email_text) 143 print('Email sent.') 144 except Exception as e: 145 # Do not propagate this email sending exception, you want to email an 146 # email exception? Just log it on console. 147 print('Sending email failed - {0}' 148 'Subject: {1}' 149 'Text: {2}').format( 150 str(e), subject, email_text) 151 152 153def ProcessArguments(argv): 154 """Processing script arguments.""" 155 parser = argparse.ArgumentParser( 156 description=('This script is used by nightly client to test gcc. ' 157 'DO NOT run it unless you know what you are doing.'), 158 usage='test_gcc_dejagnu.py options') 159 parser.add_argument('-b', 160 '--board', 161 dest='board', 162 help=('Required. Specify board type. For example ' 163 '\'lumpy\' and \'daisy\'')) 164 parser.add_argument('-r', 165 '--remote', 166 dest='remote', 167 help=('Required. Specify remote board address')) 168 parser.add_argument('-g', 169 '--gcc_dir', 170 dest='gcc_dir', 171 default='gcc.live', 172 help=('Optional. Specify gcc checkout directory.')) 173 parser.add_argument('-c', 174 '--chromeos_root', 175 dest='chromeos_root', 176 default='chromeos.live', 177 help=('Optional. Specify chromeos checkout directory.')) 178 parser.add_argument('--cleanup', 179 dest='cleanup', 180 default=None, 181 help=('Optional. Do cleanup after the test.')) 182 parser.add_argument('--runtestflags', 183 dest='runtestflags', 184 default=None, 185 help=('Optional. Options to RUNTESTFLAGS env var ' 186 'while invoking make check. ' 187 '(Mainly used for testing purpose.)')) 188 189 options = parser.parse_args(argv[1:]) 190 191 if not options.board or not options.remote: 192 raise SyntaxError('--board and --remote are mandatory options.') 193 194 return options 195 196 197def Main(argv): 198 opt = ProcessArguments(argv) 199 adapter = DejagnuAdapter(opt.board, opt.remote, opt.gcc_dir, 200 opt.chromeos_root, opt.runtestflags, opt.cleanup) 201 try: 202 adapter.SetupChromeOS() 203 adapter.SetupBoard() 204 adapter.CheckoutGCC() 205 adapter.BuildGCC() 206 ret = adapter.CheckGCC() 207 except Exception as e: 208 print(e) 209 ret = (1, '', '', str(e)) 210 finally: 211 EmailResult(ret) 212 213 return ret 214 215 216if __name__ == '__main__': 217 retval = Main(sys.argv) 218 sys.exit(retval[0]) 219