1# Copyright 2011 Google Inc. All Rights Reserved.
2# Author: kbaclawski@google.com (Krystian Baclawski)
3#
4
5from contextlib import contextmanager
6import glob
7from itertools import chain
8import logging
9import optparse
10import os.path
11import sys
12
13from manifest import Manifest
14import report
15from summary import DejaGnuTestRun
16
17
18def ExpandGlobExprList(paths):
19  """Returns an iterator that goes over expanded glob paths."""
20  return chain.from_iterable(map(glob.glob, paths))
21
22
23@contextmanager
24def OptionChecker(parser):
25  """Provides scoped environment for command line option checking."""
26  try:
27    yield
28  except SystemExit as ex:
29    parser.print_help()
30    print ''
31    sys.exit('ERROR: %s' % str(ex))
32
33
34def ManifestCommand(argv):
35  parser = optparse.OptionParser(
36      description=
37      ('Read in one or more DejaGNU summary files (.sum), parse their '
38       'content and generate manifest files.  Manifest files store a list '
39       'of failed tests that should be ignored.  Generated files are '
40       'stored in current directory under following name: '
41       '${tool}-${board}.xfail (e.g. "gcc-unix.xfail").'),
42      usage='Usage: %prog manifest [file.sum] (file2.sum ...)')
43
44  _, args = parser.parse_args(argv[2:])
45
46  with OptionChecker(parser):
47    if not args:
48      sys.exit('At least one *.sum file required.')
49
50  for filename in chain.from_iterable(map(glob.glob, args)):
51    test_run = DejaGnuTestRun.FromFile(filename)
52
53    manifest = Manifest.FromDejaGnuTestRun(test_run)
54    manifest_filename = '%s-%s.xfail' % (test_run.tool, test_run.board)
55
56    with open(manifest_filename, 'w') as manifest_file:
57      manifest_file.write(manifest.Generate())
58
59      logging.info('Wrote manifest to "%s" file.', manifest_filename)
60
61
62def ReportCommand(argv):
63  parser = optparse.OptionParser(
64      description=
65      ('Read in one or more DejaGNU summary files (.sum), parse their '
66       'content and generate a single report file in selected format '
67       '(currently only HTML).'),
68      usage=('Usage: %prog report (-m manifest.xfail) [-o report.html] '
69             '[file.sum (file2.sum ...)'))
70  parser.add_option(
71      '-o',
72      dest='output',
73      type='string',
74      default=None,
75      help=('Suppress failures for test listed in provided manifest files. '
76            '(use -m for each manifest file you want to read)'))
77  parser.add_option(
78      '-m',
79      dest='manifests',
80      type='string',
81      action='append',
82      default=None,
83      help=('Suppress failures for test listed in provided manifest files. '
84            '(use -m for each manifest file you want to read)'))
85
86  opts, args = parser.parse_args(argv[2:])
87
88  with OptionChecker(parser):
89    if not args:
90      sys.exit('At least one *.sum file required.')
91
92    if not opts.output:
93      sys.exit('Please provide name for report file.')
94
95  manifests = []
96
97  for filename in ExpandGlobExprList(opts.manifests or []):
98    logging.info('Using "%s" manifest.', filename)
99    manifests.append(Manifest.FromFile(filename))
100
101  test_runs = [DejaGnuTestRun.FromFile(filename)
102               for filename in chain.from_iterable(map(glob.glob, args))]
103
104  html = report.Generate(test_runs, manifests)
105
106  if html:
107    with open(opts.output, 'w') as html_file:
108      html_file.write(html)
109      logging.info('Wrote report to "%s" file.', opts.output)
110  else:
111    sys.exit(1)
112
113
114def HelpCommand(argv):
115  sys.exit('\n'.join([
116      'Usage: %s command [options]' % os.path.basename(argv[
117          0]), '', 'Commands:',
118      '  manifest - manage files containing a list of suppressed test failures',
119      '  report   - generate report file for selected test runs'
120  ]))
121
122
123def Main(argv):
124  try:
125    cmd_name = argv[1]
126  except IndexError:
127    cmd_name = None
128
129  cmd_map = {'manifest': ManifestCommand, 'report': ReportCommand}
130  cmd_map.get(cmd_name, HelpCommand)(argv)
131
132
133if __name__ == '__main__':
134  FORMAT = '%(asctime)-15s %(levelname)s %(message)s'
135  logging.basicConfig(format=FORMAT, level=logging.INFO)
136
137  Main(sys.argv)
138