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