blob: 8718d0e281917d337f51b7c8db97793d72c9ef89 [file] [log] [blame]
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +02001# osmo_gsm_tester: report: directory of binaries to be tested
2#
3# Copyright (C) 2016-2017 by sysmocom - s.f.m.c. GmbH
4#
5# Author: Pau Espin Pedrol <pespin@sysmocom.de>
6#
7# This program is free software: you can redistribute it and/or modify
Harald Welte27205342017-06-03 09:51:45 +02008# it under the terms of the GNU General Public License as
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +02009# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte27205342017-06-03 09:51:45 +020015# GNU General Public License for more details.
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020016#
Harald Welte27205342017-06-03 09:51:45 +020017# You should have received a copy of the GNU General Public License
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020018# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020020import math
Pau Espin Pedrol3f088da2020-03-02 10:44:09 +010021import sys
22import re
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020023from datetime import datetime
24import xml.etree.ElementTree as et
Pau Espin Pedrol5bbdab82020-02-24 18:19:10 +010025from xml.sax.saxutils import escape
Holger Hans Peter Freytherd03acdf2018-09-23 18:06:48 +010026from . import test
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020027
Pau Espin Pedrol3f088da2020-03-02 10:44:09 +010028invalid_xml_char_ranges = [(0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F), (0x7F, 0x84),
29 (0x86, 0x9F), (0xFDD0, 0xFDDF), (0xFFFE, 0xFFFF)]
30if sys.maxunicode >= 0x10000: # not narrow build
31 invalid_xml_char_ranges.extend([(0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF),
32 (0x3FFFE, 0x3FFFF), (0x4FFFE, 0x4FFFF),
33 (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF),
34 (0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF),
35 (0x9FFFE, 0x9FFFF), (0xAFFFE, 0xAFFFF),
36 (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF),
37 (0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF),
38 (0xFFFFE, 0xFFFFF), (0x10FFFE, 0x10FFFF)])
39invalid_xml_char_ranges_str = ['%s-%s' % (chr(low), chr(high))
40 for (low, high) in invalid_xml_char_ranges]
41invalid_xml_char_ranges_regex = re.compile('[%s]' % ''.join(invalid_xml_char_ranges_str))
42
43def escape_xml_invalid_characters(str):
44 replacement_char = '\uFFFD' # Unicode replacement character
45 return invalid_xml_char_ranges_regex.sub(replacement_char, escape(str))
46
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020047def trial_to_junit_write(trial, junit_path):
48 elements = et.ElementTree(element=trial_to_junit(trial))
49 elements.write(junit_path)
50
51def trial_to_junit(trial):
52 testsuites = et.Element('testsuites')
53 for suite in trial.suites:
54 testsuite = suite_to_junit(suite)
55 testsuites.append(testsuite)
56 return testsuites
57
58def suite_to_junit(suite):
59 testsuite = et.Element('testsuite')
60 testsuite.set('name', suite.name())
61 testsuite.set('hostname', 'localhost')
Neels Hofmeyrf8e61862017-06-06 23:08:07 +020062 if suite.start_timestamp:
63 testsuite.set('timestamp', datetime.fromtimestamp(round(suite.start_timestamp)).isoformat())
64 testsuite.set('time', str(math.ceil(suite.duration)))
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020065 testsuite.set('tests', str(len(suite.tests)))
Neels Hofmeyr6ccda112017-06-06 19:41:17 +020066 testsuite.set('failures', str(suite.count_test_results()[2]))
Holger Hans Peter Freytherf922a992019-02-27 04:35:17 +000067 for suite_test in suite.tests:
68 testcase = test_to_junit(suite_test)
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020069 testsuite.append(testcase)
70 return testsuite
71
Pau Espin Pedrolfd5de3d2017-11-09 14:26:35 +010072def test_to_junit(t):
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020073 testcase = et.Element('testcase')
Pau Espin Pedrolfd5de3d2017-11-09 14:26:35 +010074 testcase.set('name', t.name())
75 testcase.set('time', str(math.ceil(t.duration)))
76 if t.status == test.Test.SKIP:
Holger Hans Peter Freytherd03acdf2018-09-23 18:06:48 +010077 et.SubElement(testcase, 'skipped')
Pau Espin Pedrolfd5de3d2017-11-09 14:26:35 +010078 elif t.status == test.Test.FAIL:
Neels Hofmeyr6ccda112017-06-06 19:41:17 +020079 failure = et.SubElement(testcase, 'failure')
Pau Espin Pedrolfd5de3d2017-11-09 14:26:35 +010080 failure.set('type', t.fail_type or 'failure')
81 failure.text = t.fail_message
82 if t.fail_tb:
Neels Hofmeyr6ccda112017-06-06 19:41:17 +020083 system_err = et.SubElement(testcase, 'system-err')
Pau Espin Pedrolfd5de3d2017-11-09 14:26:35 +010084 system_err.text = t.fail_tb
85 elif t.status != test.Test.PASS:
Neels Hofmeyrf8e61862017-06-06 23:08:07 +020086 error = et.SubElement(testcase, 'error')
87 error.text = 'could not run'
Pau Espin Pedrol5bbdab82020-02-24 18:19:10 +010088 sout = et.SubElement(testcase, 'system-out')
89 log_file = t.log_file_path()
90 if log_file is not None:
91 with open(log_file, 'r') as myfile:
Pau Espin Pedrol3f088da2020-03-02 10:44:09 +010092 sout.text = escape_xml_invalid_characters(myfile.read())
Pau Espin Pedrol5bbdab82020-02-24 18:19:10 +010093 else:
94 sout.text = 'test log file not available'
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +020095 return testcase
96
97def trial_to_text(trial):
Neels Hofmeyr6ccda112017-06-06 19:41:17 +020098 suite_failures = []
99 count_fail = 0
100 count_pass = 0
101 for suite in trial.suites:
102 if suite.passed():
103 count_pass += 1
104 else:
105 count_fail += 1
106 suite_failures.append(suite_to_text(suite))
107
108 summary = ['%s: %s' % (trial.name(), trial.status)]
109 if count_fail:
110 summary.append('%d suites failed' % count_fail)
111 if count_pass:
112 summary.append('%d suites passed' % count_pass)
113 msg = [', '.join(summary)]
114 msg.extend(suite_failures)
115 return '\n'.join(msg)
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +0200116
117def suite_to_text(suite):
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +0200118 if not suite.tests:
119 return 'no tests were run.'
Neels Hofmeyr6ccda112017-06-06 19:41:17 +0200120
121 passed, skipped, failed = suite.count_test_results()
122 details = []
123 if failed:
124 details.append('fail: %d' % failed)
125 if passed:
126 details.append('pass: %d' % passed)
127 if skipped:
128 details.append('skip: %d' % skipped)
129 msgs = ['%s: %s (%s)' % (suite.status, suite.name(), ', '.join(details))]
130 msgs.extend([test_to_text(t) for t in suite.tests])
131 return '\n '.join(msgs)
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +0200132
Pau Espin Pedrolfd5de3d2017-11-09 14:26:35 +0100133def test_to_text(t):
134 msgs = ['%s: %s' % (t.status, t.name())]
135 if t.start_timestamp:
136 msgs.append('(%.1f sec)' % t.duration)
137 if t.status == test.Test.FAIL:
138 msgs.append('%s: %s' % (t.fail_type, t.fail_message))
Neels Hofmeyr6ccda112017-06-06 19:41:17 +0200139 return ' '.join(msgs)
Pau Espin Pedrol0ffb4142017-05-15 18:24:35 +0200140
141# vim: expandtab tabstop=4 shiftwidth=4