Merge lp:~lifeless/ubuntu/lucid/glib2.0/subunit into lp:ubuntu/lucid/glib2.0

Proposed by Robert Collins
Status: Rejected
Rejected by: James Westby
Proposed branch: lp:~lifeless/ubuntu/lucid/glib2.0/subunit
Merge into: lp:ubuntu/lucid/glib2.0
Diff against target: 288 lines (+256/-1)
4 files modified
debian/changelog (+6/-0)
debian/control (+2/-1)
debian/patches/80-gtester-subunit.patch (+247/-0)
debian/patches/series (+1/-0)
To merge this branch: bzr merge lp:~lifeless/ubuntu/lucid/glib2.0/subunit
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+20879@code.launchpad.net

Description of the change

This adds a patch approved upstream but pending a release, for use in the dx team test suites.

To post a comment you must log in.
48. By Robert Collins

Adjust package recommends.

Revision history for this message
James Westby (james-w) wrote :

glib2.0 is not going to be under active development going forward,
so seb128 said he isn't going to invest the time in merging this.

Thanks,

James

Revision history for this message
Robert Collins (lifeless) wrote :

So where should people put improvements to the gnome testing
infrastructure now ?

Revision history for this message
James Westby (james-w) wrote :

On Wed, 04 Aug 2010 00:18:45 -0000, Robert Collins <email address hidden> wrote:
> So where should people put improvements to the gnome testing
> infrastructure now ?

Maybe I misunderstood the comment, so I suggest you contact seb to
discuss it with him.

<seb128> james_w, can you delete the glib2.0 one on
http://qa.ubuntu.com/reports/sponsoring/index.html as well?
<seb128> it's deprecated

Thanks,

James

Unmerged revisions

48. By Robert Collins

Adjust package recommends.

47. By Robert Collins

Add subunit support to gtester-report.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2010-02-22 15:00:46 +0000
+++ debian/changelog 2010-03-08 08:18:33 +0000
@@ -1,3 +1,9 @@
1glib2.0 (2.23.4-1ubuntu2) lucid; urgency=low
2
3 * Add subunit support to gtester-report.
4
5 -- Robert Collins <robert@canonical.com> Mon, 08 Mar 2010 15:58:19 +1100
6
1glib2.0 (2.23.4-1ubuntu1) lucid; urgency=low7glib2.0 (2.23.4-1ubuntu1) lucid; urgency=low
28
3 * Resync on Debian9 * Resync on Debian
410
=== modified file 'debian/control'
--- debian/control 2010-02-22 15:00:46 +0000
+++ debian/control 2010-03-08 08:18:33 +0000
@@ -66,7 +66,8 @@
66 pkg-config (>= 0.14.0),66 pkg-config (>= 0.14.0),
67 zlib1g-dev67 zlib1g-dev
68Recommends: python68Recommends: python
69Suggests: libglib2.0-doc69Suggests: libglib2.0-doc,
70 python-subunit
70Replaces: libglib1.3-dev71Replaces: libglib1.3-dev
71Conflicts: libglib1.3-dev72Conflicts: libglib1.3-dev
72Description: Development files for the GLib library73Description: Development files for the GLib library
7374
=== added file 'debian/patches/80-gtester-subunit.patch'
--- debian/patches/80-gtester-subunit.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/80-gtester-subunit.patch 2010-03-08 08:18:33 +0000
@@ -0,0 +1,247 @@
1# Upstream: https://bugzilla.gnome.org/show_bug.cgi?id=611869
2# Description: adds subunit support to gtester-report
3=== modified file 'a/glib/gtester-report'
4--- a/glib/gtester-report 2009-12-19 00:57:03 +0000
5+++ b/glib/gtester-report 2010-03-05 04:42:43 +0000
6@@ -17,7 +17,19 @@
7 # License along with this library; if not, write to the
8 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
9 # Boston, MA 02111-1307, USA.
10+import datetime
11+import optparse
12 import sys, re, xml.dom.minidom
13+
14+try:
15+ import subunit
16+ from subunit import iso8601
17+ from testtools.content import Content, ContentType
18+ mime_utf8 = ContentType('text', 'plain', {'charset': 'utf8'})
19+except ImportError:
20+ subunit = None
21+
22+
23 pkginstall_configvars = {
24 #@PKGINSTALL_CONFIGVARS_IN24LINES@ # configvars are substituted upon script installation
25 }
26@@ -144,8 +156,25 @@
27 self.last_binary.random_seed = node_as_text (rseed)
28 self.process_children (node)
29
30-# HTML report generation class
31-class ReportWriter (TreeProcess):
32+
33+class ReportWriter(object):
34+ """Base class for reporting."""
35+
36+ def __init__(self, binary_list):
37+ self.binaries = binary_list
38+
39+ def _error_text(node):
40+ """Get a string representing the error children of node."""
41+ rlist = list_children(node, 'error')
42+ txt = ''
43+ for enode in rlist:
44+ txt += node_as_text (enode)
45+ if txt and txt[-1] != '\n':
46+ txt += '\n'
47+ return txt
48+
49+
50+class HTMLReportWriter(ReportWriter):
51 # Javascript/CSS snippet to toggle element visibility
52 cssjs = r'''
53 <style type="text/css" media="screen">
54@@ -186,9 +215,8 @@
55 }
56 --></script>
57 '''
58- def __init__ (self, binary_list):
59- TreeProcess.__init__ (self)
60- self.binaries = binary_list
61+ def __init__(self, binary_list):
62+ ReportWriter.__init__(self, binary_list)
63 self.bcounter = 0
64 self.tcounter = 0
65 self.total_tcounter = 0
66@@ -219,12 +247,7 @@
67 self.oprint ('<td>%s %s</td> <td align="right">%s</td> \n' % (html_indent_string (4), path, duration))
68 perflist = list_children (node, 'performance')
69 if result != 'success':
70- rlist = list_children (node, 'error')
71- txt = ''
72- for enode in rlist:
73- txt += node_as_text (enode)
74- if txt and txt[-1] != '\n':
75- txt += '\n'
76+ txt = self._error_text(node)
77 txt = re.sub (r'"', r'\\"', txt)
78 txt = re.sub (r'\n', r'\\n', txt)
79 txt = re.sub (r'&', r'&amp;', txt)
80@@ -313,46 +336,132 @@
81 self.oprint ('</body>\n')
82 self.oprint ('</html>\n')
83
84+
85+class SubunitWriter(ReportWriter):
86+ """Reporter to output a subunit stream."""
87+
88+ def printout(self):
89+ reporter = subunit.TestProtocolClient(sys.stdout)
90+ for binary in self.binaries:
91+ for tc in binary.testcases:
92+ test = GTestCase(tc, binary)
93+ test.run(reporter)
94+
95+
96+class GTestCase(object):
97+ """A representation of a gtester test result as a pyunit TestCase."""
98+
99+ def __init__(self, case, binary):
100+ """Create a GTestCase for case `case` from binary program `binary`."""
101+ self._case = case
102+ self._binary = binary
103+ # the name of the case - e.g. /dbusmenu/glib/objects/menuitem/props_boolstr
104+ self._path = attribute_as_text(self._case, 'path')
105+
106+ def id(self):
107+ """What test is this? Returns the gtester path for the testcase."""
108+ return self._path
109+
110+ def _get_details(self):
111+ """Calculate a details dict for the test - attachments etc."""
112+ details = {}
113+ result = attribute_as_text(self._case, 'result', 'status')
114+ details['filename'] = Content(mime_utf8, lambda:[self._binary.file])
115+ details['random_seed'] = Content(mime_utf8,
116+ lambda:[self._binary.random_seed])
117+ if self._get_outcome() == 'addFailure':
118+ # Extract the error details. Skips have no details because its not
119+ # skip like unittest does, instead the runner just bypasses N test.
120+ txt = self._error_text(self._case)
121+ details['error'] = Content(mime_utf8, lambda:[txt])
122+ if self._get_outcome() == 'addSuccess':
123+ # Sucessful tests may have performance metrics.
124+ perflist = list_children(self._case, 'performance')
125+ if perflist:
126+ presults = []
127+ for perf in perflist:
128+ pmin = bool (int (attribute_as_text (perf, 'minimize')))
129+ pmax = bool (int (attribute_as_text (perf, 'maximize')))
130+ pval = float (attribute_as_text (perf, 'value'))
131+ txt = node_as_text (perf)
132+ txt = 'Performance(' + (pmin and 'minimized' or 'maximized'
133+ ) + '): ' + txt.strip() + '\n'
134+ presults += [(pval, txt)]
135+ presults.sort()
136+ perf_details = [e[1] for e in presults]
137+ details['performance'] = Content(mime_utf8, lambda:perf_details)
138+ return details
139+
140+ def _get_outcome(self):
141+ if int(attribute_as_text(self._case, 'skipped') + '0'):
142+ return 'addSkip'
143+ outcome = attribute_as_text(self._case, 'result', 'status')
144+ if outcome == 'success':
145+ return 'addSuccess'
146+ else:
147+ return 'addFailure'
148+
149+ def run(self, result):
150+ time = datetime.datetime.utcnow().replace(tzinfo=iso8601.Utc())
151+ result.time(time)
152+ result.startTest(self)
153+ try:
154+ outcome = self._get_outcome()
155+ details = self._get_details()
156+ # Only provide a duration IFF outcome == 'addSuccess' - the main
157+ # parser claims bogus results otherwise: in that case emit time as
158+ # zero perhaps.
159+ if outcome == 'addSuccess':
160+ duration = float(node_as_text(self._case, 'duration'))
161+ duration = duration * 1000000
162+ timedelta = datetime.timedelta(0, 0, duration)
163+ time = time + timedelta
164+ result.time(time)
165+ getattr(result, outcome)(self, details=details)
166+ finally:
167+ result.stopTest(self)
168+
169+
170+
171 # main program handling
172-def parse_files_and_args ():
173- from sys import argv, stdin
174- files = []
175- arg_iter = sys.argv[1:].__iter__()
176- rest = len (sys.argv) - 1
177- for arg in arg_iter:
178- rest -= 1
179- if arg == '--help' or arg == '-h':
180- print_help ()
181- sys.exit (0)
182- elif arg == '--version' or arg == '-v':
183- print_help (False)
184- sys.exit (0)
185- else:
186- files = files + [ arg ]
187- return files
188-
189-def print_help (with_help = True):
190- import os
191- print "gtester-report (GLib utils) version", pkginstall_configvars.get ('glib-version', '0.0-uninstalled')
192- if not with_help:
193- return
194- print "Usage: %s [OPTIONS] <gtester-log.xml>" % os.path.basename (sys.argv[0])
195- print "Generate HTML reports from the XML log files generated by gtester."
196- print "Options:"
197- print " --help, -h print this help message"
198- print " --version, -v print version info"
199+def parse_opts():
200+ """Parse program options.
201+
202+ :return: An options object and the program arguments.
203+ """
204+ parser = optparse.OptionParser()
205+ parser.version = pkginstall_configvars.get ('glib-version', '0.0-uninstalled')
206+ parser.usage = "%prog [OPTIONS] <gtester-log.xml>"
207+ parser.description = "Generate HTML reports from the XML log files generated by gtester."
208+ parser.epilog = "gtester-report (GLib utils) version %s."% (parser.version,)
209+ parser.add_option("-v", "--version", action="store_true", dest="version", default=False,
210+ help="Show program version.")
211+ parser.add_option("-s", "--subunit", action="store_true", dest="subunit", default=False,
212+ help="Output subunit [See https://launchpad.net/subunit/"
213+ " Needs python-subunit]")
214+ options, files = parser.parse_args()
215+ if options.version:
216+ print parser.epilog
217+ return None, None
218+ if len(files) != 1:
219+ parser.error("Must supply a log file to parse.")
220+ if options.subunit and subunit is None:
221+ parser.error("python-subunit is not installed.")
222+ return options, files
223+
224
225 def main():
226- from sys import argv, stdin
227- files = parse_files_and_args()
228- if len (files) != 1:
229- print_help (True)
230- sys.exit (1)
231+ options, files = parse_opts()
232+ if options is None:
233+ return 0
234 xd = xml.dom.minidom.parse (files[0])
235 rr = ReportReader()
236 rr.trampoline (xd)
237- rw = ReportWriter (rr.binary_list())
238- rw.printout()
239+ if not options.subunit:
240+ HTMLReportWriter(rr.binary_list()).printout()
241+ else:
242+ SubunitWriter(rr.binary_list()).printout()
243+
244
245 if __name__ == '__main__':
246 main()
247
0248
=== modified file 'debian/patches/series'
--- debian/patches/series 2010-02-22 15:00:46 +0000
+++ debian/patches/series 2010-03-08 08:18:33 +0000
@@ -5,3 +5,4 @@
505-dont-fail-a-couple-of-tests-when-running-as-root.patch505-dont-fail-a-couple-of-tests-when-running-as-root.patch
660_wait-longer-for-threads-to-die.patch660_wait-longer-for-threads-to-die.patch
771_gio_launch_handler.patch771_gio_launch_handler.patch
880-gtester-subunit.patch

Subscribers

People subscribed via source and target branches

to all changes: