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

Proposed by Robert Collins on 2010-03-08
Status: Rejected
Rejected by: James Westby on 2010-08-03
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 2010-03-08 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 on 2010-03-08

Adjust package recommends.

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

Robert Collins (lifeless) wrote :

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

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 on 2010-03-08

Adjust package recommends.

47. By Robert Collins on 2010-03-08

Add subunit support to gtester-report.

Preview Diff

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

Subscribers

People subscribed via source and target branches

to all changes: