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