blob: 90055e3530c918342c3dbf640d772d476cfd50da [file] [log] [blame]
Craig Tiller6169d5f2016-03-31 07:46:18 -07001# Copyright 2015, Google Inc.
Adele Zhou2271ab52015-10-28 13:59:14 -07002# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met:
7#
8# * Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10# * Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following disclaimer
12# in the documentation and/or other materials provided with the
13# distribution.
14# * Neither the name of Google Inc. nor the names of its
15# contributors may be used to endorse or promote products derived from
16# this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30"""Generate XML and HTML test reports."""
31
siddharthshukla0589e532016-07-07 16:08:01 +020032from __future__ import print_function
33
Adele Zhou3bc7ba42015-11-05 10:21:58 -080034try:
35 from mako.runtime import Context
36 from mako.template import Template
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -080037 from mako import exceptions
Adele Zhou3bc7ba42015-11-05 10:21:58 -080038except (ImportError):
murgatroid995d6ae932016-10-28 11:48:22 -070039 pass # Mako not installed but it is ok.
Adele Zhou2271ab52015-10-28 13:59:14 -070040import os
Adele Zhoud01cbe32015-11-02 14:20:43 -080041import string
Adele Zhou2271ab52015-10-28 13:59:14 -070042import xml.etree.cElementTree as ET
43
44
Adele Zhoud01cbe32015-11-02 14:20:43 -080045def _filter_msg(msg, output_format):
46 """Filters out nonprintable and illegal characters from the message."""
47 if output_format in ['XML', 'HTML']:
48 # keep whitespaces but remove formfeed and vertical tab characters
49 # that make XML report unparseable.
50 filtered_msg = filter(
51 lambda x: x in string.printable and x != '\f' and x != '\v',
Jan Tattermusch60ab05a2016-02-25 17:42:44 -080052 msg.decode('UTF-8', 'ignore'))
Adele Zhoud01cbe32015-11-02 14:20:43 -080053 if output_format == 'HTML':
54 filtered_msg = filtered_msg.replace('"', '"')
55 return filtered_msg
56 else:
57 return msg
58
59
Jan Tattermuschcfcc0752016-10-09 17:02:34 +020060def render_junit_xml_report(resultset, xml_report, suite_package='grpc',
61 suite_name='tests'):
Adele Zhou2271ab52015-10-28 13:59:14 -070062 """Generate JUnit-like XML report."""
63 root = ET.Element('testsuites')
Jan Tattermuschcfcc0752016-10-09 17:02:34 +020064 testsuite = ET.SubElement(root, 'testsuite', id='1', package=suite_package,
65 name=suite_name)
murgatroid995d6ae932016-10-28 11:48:22 -070066 for shortname, results in resultset.iteritems():
Adele Zhou2271ab52015-10-28 13:59:14 -070067 for result in results:
murgatroid995d6ae932016-10-28 11:48:22 -070068 xml_test = ET.SubElement(testsuite, 'testcase', name=shortname)
Adele Zhou2271ab52015-10-28 13:59:14 -070069 if result.elapsed_time:
70 xml_test.set('time', str(result.elapsed_time))
Adele Zhoud01cbe32015-11-02 14:20:43 -080071 ET.SubElement(xml_test, 'system-out').text = _filter_msg(result.message,
72 'XML')
Adele Zhou2271ab52015-10-28 13:59:14 -070073 if result.state == 'FAILED':
74 ET.SubElement(xml_test, 'failure', message='Failure')
75 elif result.state == 'TIMEOUT':
76 ET.SubElement(xml_test, 'error', message='Timeout')
Matt Kwong5c691c62016-10-20 17:11:18 -070077 elif result.state == 'SKIPPED':
78 ET.SubElement(xml_test, 'skipped', message='Skipped')
Adele Zhou2271ab52015-10-28 13:59:14 -070079 tree = ET.ElementTree(root)
80 tree.write(xml_report, encoding='UTF-8')
81
82
Adele Zhou3bc7ba42015-11-05 10:21:58 -080083def render_interop_html_report(
murgatroid995d6ae932016-10-28 11:48:22 -070084 client_langs, server_langs, test_cases, auth_test_cases, http2_cases,
Adele Zhoub9e66cc2016-02-03 13:12:23 -080085 resultset, num_failures, cloud_to_prod, prod_servers, http2_interop):
Adele Zhou3bc7ba42015-11-05 10:21:58 -080086 """Generate HTML report for interop tests."""
Adele Zhou12877c92015-12-09 11:22:25 -080087 template_file = 'tools/run_tests/interop_html_report.template'
Adele Zhou3bc7ba42015-11-05 10:21:58 -080088 try:
89 mytemplate = Template(filename=template_file, format_exceptions=True)
90 except NameError:
siddharthshukla0589e532016-07-07 16:08:01 +020091 print('Mako template is not installed. Skipping HTML report generation.')
Adele Zhou3bc7ba42015-11-05 10:21:58 -080092 return
93 except IOError as e:
siddharthshukla0589e532016-07-07 16:08:01 +020094 print('Failed to find the template %s: %s' % (template_file, e))
Adele Zhou3bc7ba42015-11-05 10:21:58 -080095 return
Adele Zhou2271ab52015-10-28 13:59:14 -070096
Adele Zhou3bc7ba42015-11-05 10:21:58 -080097 sorted_test_cases = sorted(test_cases)
98 sorted_auth_test_cases = sorted(auth_test_cases)
99 sorted_http2_cases = sorted(http2_cases)
100 sorted_client_langs = sorted(client_langs)
101 sorted_server_langs = sorted(server_langs)
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800102 sorted_prod_servers = sorted(prod_servers)
Adele Zhou3bc7ba42015-11-05 10:21:58 -0800103
murgatroid995d6ae932016-10-28 11:48:22 -0700104 args = {'client_langs': sorted_client_langs,
Adele Zhou3bc7ba42015-11-05 10:21:58 -0800105 'server_langs': sorted_server_langs,
106 'test_cases': sorted_test_cases,
107 'auth_test_cases': sorted_auth_test_cases,
108 'http2_cases': sorted_http2_cases,
109 'resultset': resultset,
110 'num_failures': num_failures,
111 'cloud_to_prod': cloud_to_prod,
Adele Zhoub9e66cc2016-02-03 13:12:23 -0800112 'prod_servers': sorted_prod_servers,
Adele Zhou3bc7ba42015-11-05 10:21:58 -0800113 'http2_interop': http2_interop}
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -0800114
murgatroid995d6ae932016-10-28 11:48:22 -0700115 html_report_out_dir = 'reports'
Adele Zhou12877c92015-12-09 11:22:25 -0800116 if not os.path.exists(html_report_out_dir):
murgatroid995d6ae932016-10-28 11:48:22 -0700117 os.mkdir(html_report_out_dir)
Adele Zhou12877c92015-12-09 11:22:25 -0800118 html_file_path = os.path.join(html_report_out_dir, 'index.html')
Carl Mastrangeloe7f8e8e2015-12-08 17:22:44 -0800119 try:
120 with open(html_file_path, 'w') as output_file:
121 mytemplate.render_context(Context(output_file, **args))
122 except:
123 print(exceptions.text_error_template().render())
124 raise