13d69d8b76f487f74be152ed15b75438e7de947bdkbaclawski# Copyright 2011 Google Inc. All Rights Reserved.
23d69d8b76f487f74be152ed15b75438e7de947bdkbaclawski# Author: kbaclawski@google.com (Krystian Baclawski)
33d69d8b76f487f74be152ed15b75438e7de947bdkbaclawski#
43d69d8b76f487f74be152ed15b75438e7de947bdkbaclawski
5fe30dd5ad4357e9846038cb5fe0e4bf4a17a3f71kbaclawskiimport logging
63d69d8b76f487f74be152ed15b75438e7de947bdkbaclawskiimport os.path
73d69d8b76f487f74be152ed15b75438e7de947bdkbaclawski
8ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawskiRESULT_DESCRIPTION = {
9ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'ERROR': 'DejaGNU errors',
10ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'FAIL': 'Failed tests',
11ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'NOTE': 'DejaGNU notices',
12ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'PASS': 'Passed tests',
13ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'UNRESOLVED': 'Unresolved tests',
14ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'UNSUPPORTED': 'Unsupported tests',
15ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'UNTESTED': 'Not executed tests',
16ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'WARNING': 'DejaGNU warnings',
17ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'XFAIL': 'Expected test failures',
18f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano    'XPASS': 'Unexpectedly passed tests'
19f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano}
20ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
21ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawskiRESULT_GROUPS = {
22ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'Successes': ['PASS', 'XFAIL'],
23ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'Failures': ['FAIL', 'XPASS', 'UNRESOLVED'],
24ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    'Suppressed': ['!FAIL', '!XPASS', '!UNRESOLVED', '!ERROR'],
25f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano    'Framework': ['UNTESTED', 'UNSUPPORTED', 'ERROR', 'WARNING', 'NOTE']
26f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano}
27ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
28ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawskiROOT_PATH = os.path.dirname(os.path.abspath(__file__))
29ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
30ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
31ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawskidef _GetResultDescription(name):
32ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  if name.startswith('!'):
33ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    name = name[1:]
34ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
35ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  try:
36ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    return RESULT_DESCRIPTION[name]
37ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  except KeyError:
38ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    raise ValueError('Unknown result: "%s"' % name)
39ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
40ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
41ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawskidef _PrepareSummary(res_types, summary):
42f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano
43ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  def GetResultCount(res_type):
44ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    return summary.get(res_type, 0)
45ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
46f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano  return [(_GetResultDescription(rt), GetResultCount(rt)) for rt in res_types]
47ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
48ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
49ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawskidef _PrepareTestList(res_types, tests):
50f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano
51ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  def GetTestsByResult(res_type):
52ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    return [(test.name, test.variant or '')
53f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano            for test in sorted(tests) if test.result == res_type]
54ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
55ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  return [(_GetResultDescription(rt), GetTestsByResult(rt))
56ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski          for rt in res_types if rt != 'PASS']
57ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
58ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
59ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawskidef Generate(test_runs, manifests):
60ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  """Generate HTML report from provided test runs.
61ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
62ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  Args:
63ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    test_runs: DejaGnuTestRun objects list.
64ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    manifests: Manifest object list that will drive test result suppression.
65ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
66ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  Returns:
67ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    String to which the HTML report was rendered.
68ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  """
69ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  tmpl_args = []
70ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
71ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  for test_run_id, test_run in enumerate(test_runs):
72ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    logging.info('Generating report for: %s.', test_run)
73ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
74ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    test_run.CleanUpTestResults()
75ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    test_run.SuppressTestResults(manifests)
76ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
77ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    # Generate summary and test list for each result group
78ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    groups = {}
79ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
80ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    for res_group, res_types in RESULT_GROUPS.items():
81ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski      summary_all = _PrepareSummary(res_types, test_run.summary)
82ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski      tests_all = _PrepareTestList(res_types, test_run.results)
83ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
84ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski      has_2nd = lambda tuple2: bool(tuple2[1])
85ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski      summary = filter(has_2nd, summary_all)
86ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski      tests = filter(has_2nd, tests_all)
87ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
88ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski      if summary or tests:
89ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski        groups[res_group] = {'summary': summary, 'tests': tests}
90ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
91ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    tmpl_args.append({
92ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski        'id': test_run_id,
93ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski        'name': '%s @%s' % (test_run.tool, test_run.board),
94f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano        'groups': groups
95f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano    })
96ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
97ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  logging.info('Rendering report in HTML format.')
98ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
99ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  try:
100ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    from django import template
101ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    from django.template import loader
102ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    from django.conf import settings
103ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  except ImportError:
104ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    logging.error('Django framework not installed!')
105ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    logging.error('Failed to generate report in HTML format!')
106ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski    return ''
107ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
108f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano  settings.configure(DEBUG=True,
109f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbeLuis Lozano                     TEMPLATE_DEBUG=True,
110ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski                     TEMPLATE_DIRS=(ROOT_PATH,))
111ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
112ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  tmpl = loader.get_template('report.html')
113ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  ctx = template.Context({'test_runs': tmpl_args})
114ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski
115ee9d100c66939659aa3f3e5377772da59615f4e1kbaclawski  return tmpl.render(ctx)
116