test_gcc_dejagnu.py revision 6aebeb10e517878cb76044e6a1d46f75c2fd93d6
1#!/usr/bin/python
2#
3# Copyright 2010 Google Inc. All Rights Reserved.
4
5"""Script adapter used by automation client for testing dejagnu.
6   This is not intended to be run on command line.
7   To kick off a single dejagnu run, use chromeos/v14/dejagnu/run_dejagnu.py
8"""
9
10__author__ = 'shenhan@google.com (Han Shen)'
11
12import optparse
13import os
14from os import path
15import sys
16import setup_chromeos
17import build_tc
18
19from dejagnu import run_dejagnu
20from utils import command_executer
21from utils import email_sender
22
23class DejagnuAdapter(object):
24
25  # TODO(shenhan): move these to constants.py.
26  _CHROMIUM_GCC_GIT = ("http://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,
33               chromeos_root, runtestflags, 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__,
43           "--dir=" + self._chromeos_root, "--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, terminated_timeout=4000)
57    if ret:
58      raise Exception("Failed to setup board.")
59
60  def CheckoutGCC(self):
61    cmd = "git clone {0} {1} && cd {1} && git checkout {2}".format(
62      self._CHROMIUM_GCC_GIT, self._gcc_dir, self._CHROMIUM_GCC_BRANCH)
63
64    ret = self._cmd_exec.RunCommand(cmd, terminated_timeout=300)
65    if ret:
66      raise Exception("Failed to checkout gcc.")
67    ## Handle build_tc bug.
68    cmd = ("touch {0}/gcc/config/arm/arm-tune.md " + \
69        "{0}/gcc/config/arm/arm-tables.opt").format(self._gcc_dir)
70    ret = self._cmd_exec.RunCommand(cmd)
71
72  def BuildGCC(self):
73    build_gcc_args = [build_tc.__file__,
74                      "--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__,
83            "--board=" + self._board,
84            "--chromeos_root=" + self._chromeos_root,
85            "--mount=" + self._gcc_dir,
86            "--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(str):
97  if not str:
98    return 0
99  start_counting = False
100  n_failures = 0
101  for l in 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# Do not throw any exception in this function!
114def EmailResult(result):
115  email_to = ['c-compiler-chrome@google.com']
116  email_from = ['dejagnu-job@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 = optparse.OptionParser(description=(
156      '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_option('-b', '--board', dest='board',
160                    help=('Required. Specify board type. For example '
161                          '\'lumpy\' and \'daisy\''))
162  parser.add_option('-r', '--remote', dest='remote',
163                    help=('Required. Specify remote board address'))
164  parser.add_option('-g', '--gcc_dir', dest='gcc_dir', default='gcc.live',
165                    help=('Optional. Specify gcc checkout directory.'))
166  parser.add_option('-c', '--chromeos_root', dest='chromeos_root',
167                    default='chromeos.live',
168                    help=('Optional. Specify chromeos checkout directory.'))
169  parser.add_option('--cleanup', dest='cleanup', default=None,
170                    help=('Optional. Do cleanup after the test.'))
171  parser.add_option('--runtestflags', dest='runtestflags', default=None,
172                    help=('Optional. Options to RUNTESTFLAGS env var '
173                          'while invoking make check. '
174                          '(Mainly used for testing purpose.)'))
175
176  options, args = parser.parse_args(argv)
177
178  if not options.board or not options.remote:
179    raise Exception("--board and --remote are mandatory options.")
180
181  return options
182
183
184def Main(argv):
185  opt = ProcessArguments(argv)
186  adapter = DejagnuAdapter(
187    opt.board, opt.remote, opt.gcc_dir, opt.chromeos_root,
188    opt.runtestflags, opt.cleanup)
189  try:
190    adapter.SetupChromeOS()
191    adapter.SetupBoard()
192    adapter.CheckoutGCC()
193    adapter.BuildGCC()
194    ret = adapter.CheckGCC()
195  except Exception as e:
196    print e
197    ret = (1, '', '', str(e))
198  finally:
199    EmailResult(ret)
200    return ret
201
202
203if __name__ == "__main__":
204  retval = Main(sys.argv)
205  sys.exit(retval[0])
206