Add more structure constructor tests.
[piglit/hramrach.git] / piglit-summary-html.py
blob35e49e04e678bf10351340f7cad1f8d864be2475
1 #!/usr/bin/env python
3 # Permission is hereby granted, free of charge, to any person
4 # obtaining a copy of this software and associated documentation
5 # files (the "Software"), to deal in the Software without
6 # restriction, including without limitation the rights to use,
7 # copy, modify, merge, publish, distribute, sublicense, and/or
8 # sell copies of the Software, and to permit persons to whom the
9 # Software is furnished to do so, subject to the following
10 # conditions:
12 # This permission notice shall be included in all copies or
13 # substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
18 # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21 # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 # DEALINGS IN THE SOFTWARE.
24 from getopt import getopt, GetoptError
25 import cgi
26 import os
27 import sys
29 import framework.core as core
30 import framework.summary
33 #############################################################################
34 ##### Auxiliary functions
35 #############################################################################
37 def testPathToHtmlFilename(path):
38 return 'test_' + filter(lambda s: s.isalnum() or s == '_', path.replace('/', '__')) + '.html'
41 #############################################################################
42 ##### HTML output
43 #############################################################################
45 def readfile(filename):
46 f = open(filename, "r")
47 s = f.read()
48 f.close()
49 return s
51 def writefile(filename, text):
52 f = open(filename, "w")
53 f.write(text)
54 f.close()
56 templatedir = os.path.join(os.path.dirname(__file__), 'templates')
57 Result = readfile(os.path.join(templatedir, 'result.html'))
58 ResultDetail = readfile(os.path.join(templatedir, 'result_detail.html'))
59 ResultList = readfile(os.path.join(templatedir, 'result_list.html'))
60 ResultListItem = readfile(os.path.join(templatedir, 'result_listitem.html'))
61 ResultMString = readfile(os.path.join(templatedir, 'result_mstring.html'))
63 Index = readfile(os.path.join(templatedir, 'index.html'))
64 IndexTestrun = readfile(os.path.join(templatedir, 'index_testrun.html'))
65 IndexTestrunB = readfile(os.path.join(templatedir, 'index_testrunb.html'))
66 IndexTestrunBHref = readfile(os.path.join(templatedir, 'index_testrunb_href.html'))
67 IndexGroup = readfile(os.path.join(templatedir, 'index_group.html'))
68 IndexGroupTestrun = readfile(os.path.join(templatedir, 'index_group_testrun.html'))
69 IndexGroupGroup = readfile(os.path.join(templatedir, 'index_groupgroup.html'))
70 IndexTest = readfile(os.path.join(templatedir, 'index_test.html'))
71 IndexTestTestrun = readfile(os.path.join(templatedir, 'index_test_testrun.html'))
73 Testrun = readfile(os.path.join(templatedir, 'testrun.html'))
75 SummaryPages = {
76 'all': 'index.html',
77 'changes': 'changes.html',
78 'problems': 'problems.html'
81 def buildDetailValue(detail):
82 if type(detail) == list:
83 items = ''
85 for d in detail:
86 items = items + ResultListItem % { 'detail': buildDetailValue(d) }
88 return ResultList % { 'items': items }
89 elif type(detail) == str and detail[0:3] == '@@@':
90 return ResultMString % { 'detail': cgi.escape(detail[3:]) }
92 return cgi.escape(str(detail))
95 def buildDetails(testResult):
96 details = []
97 for name in testResult:
98 if type(name) != str or name == 'result':
99 continue
101 value = buildDetailValue(testResult[name])
102 details += [(name, value)]
104 details.sort(lambda a, b: len(a[1])-len(b[1]))
106 text = ''
107 alternate = 'a'
108 for name, value in details:
109 text += ResultDetail % locals()
111 if alternate == 'a':
112 alternate = 'b'
113 else:
114 alternate = 'a'
116 return text
119 def writeResultHtml(test, testResult, filename):
120 path = test.path
121 name = test.name
122 status = testResult.status
124 if 'result' in testResult:
125 result = testResult['result']
126 else:
127 result = '?'
129 details = buildDetails(testResult)
131 writefile(filename, Result % locals())
133 def writeTestrunHtml(testrun, filename):
134 detaildict = dict(filter(lambda item: item[0] in testrun.globalkeys, testrun.__dict__.items()))
135 details = buildDetails(detaildict)
136 name = testrun.name
137 codename = testrun.codename
139 writefile(filename, Testrun % locals())
141 def buildTestSummary(indent, alternate, testsummary):
142 tenindent = 10 - indent
143 path = testsummary.path
144 name = testsummary.name
145 testruns = "".join([IndexTestTestrun % {
146 'alternate': alternate,
147 'status': result.status,
148 'link': result.testrun.codename + '/' + testPathToHtmlFilename(path)
149 } for result in testsummary.results])
151 return IndexTest % locals()
154 def buildGroupSummaryTestrun(groupresult):
155 passnr = groupresult.passvector.passnr
156 warnnr = groupresult.passvector.warnnr
157 failnr = groupresult.passvector.failnr
158 skipnr = groupresult.passvector.skipnr
159 totalnr = passnr + warnnr + failnr # do not count skips
161 if failnr > 0:
162 status = 'fail'
163 elif warnnr > 0:
164 status = 'warn'
165 elif passnr > 0:
166 status = 'pass'
167 else:
168 status = 'skip'
170 return IndexGroupTestrun % locals()
173 def buildGroupSummary(indent, groupsummary, showcurrent):
174 tenindent = 10 - indent
176 items = ''
177 alternate = 'a'
178 path = groupsummary.path
179 name = groupsummary.name
180 names = groupsummary.children.keys()
182 if showcurrent == 'changes':
183 names = filter(lambda n: groupsummary.children[n].changes, names)
184 elif showcurrent == 'problems':
185 names = filter(lambda n: groupsummary.children[n].problems, names)
187 names.sort()
188 for n in names:
189 child = groupsummary.children[n]
190 if isinstance(child, framework.summary.GroupSummary):
191 items = items + IndexGroupGroup % {
192 'group': buildGroupSummary(indent+1, child, showcurrent)
194 else:
195 items = items + buildTestSummary(indent+1, alternate, child)
197 if alternate == 'a':
198 alternate = 'b'
199 else:
200 alternate = 'a'
202 testruns = "".join([buildGroupSummaryTestrun(result)
203 for result in groupsummary.results])
205 return IndexGroup % locals()
208 def writeSummaryHtml(summary, summaryDir, showcurrent):
209 """\
210 results is an array containing the top-level results dictionarys.
212 def link(to):
213 if to == showcurrent:
214 return to
215 else:
216 page = SummaryPages[to]
217 return '<a href="%(page)s">%(to)s</a>' % locals()
219 def testrunb(tr):
220 if 'href' in tr.__dict__:
221 return IndexTestrunBHref % tr.__dict__
222 else:
223 return IndexTestrunB % tr.__dict__
225 group = buildGroupSummary(1, summary.root, showcurrent)
226 testruns = "".join([IndexTestrun % tr.__dict__ for tr in summary.testruns])
227 testrunsb = "".join([testrunb(tr) for tr in summary.testruns])
229 tolist = SummaryPages.keys()
230 tolist.sort()
231 showlinks = " | ".join([link(to) for to in tolist])
233 writefile(summaryDir + '/' + SummaryPages[showcurrent], Index % locals())
236 #############################################################################
237 ##### Main program
238 #############################################################################
239 def usage():
240 USAGE = """\
241 Usage: %(progName)s [options] [summary-dir] [test.results]...
243 Options:
244 -f, --full Prefer the full results over the
245 -h, --help Show this message
246 -o, --overwrite Overwrite existing directories
247 -l, --list=listfile Use test results from a list file
249 Example:
250 %(progName)s summary/mysum results/all.results
252 Example list file:
254 [ 'test.result', { name: 'override-name' } ],
255 [ 'other.result' ]
258 print USAGE % {'progName': sys.argv[0]}
259 sys.exit(1)
262 def parse_listfile(filename):
263 file = open(filename, "r")
264 code = "".join([s for s in file])
265 file.close()
266 return eval(code)
268 def loadresult(descr, OptionPreferSummary):
269 result = core.loadTestResults(descr[0], OptionPreferSummary)
270 if len(descr) > 1:
271 result.__dict__.update(descr[1])
272 return result
274 def main():
275 try:
276 options, args = getopt(sys.argv[1:], "hofl:", [ "help", "overwrite", "full", "list" ])
277 except GetoptError:
278 usage()
280 OptionOverwrite = False
281 OptionPreferSummary = True
282 OptionList = []
283 for name, value in options:
284 if name == "-h" or name == "--help":
285 usage()
286 elif name == "-o" or name == "--overwrite":
287 OptionOverwrite = True
288 elif name == "-f" or name == "--full":
289 OptionPreferSummary = False
290 elif name == "-l" or name == "--list":
291 OptionList += parse_listfile(value)
293 OptionList += [[name] for name in args[1:]]
295 if len(args) < 1 or len(OptionList) == 0:
296 usage()
298 summaryDir = args[0]
299 core.checkDir(summaryDir, not OptionOverwrite)
301 results = [loadresult(descr, OptionPreferSummary) for descr in OptionList]
303 summary = framework.summary.Summary(results)
304 for j in range(len(summary.testruns)):
305 tr = summary.testruns[j]
306 tr.codename = filter(lambda s: s.isalnum(), tr.name)
307 dirname = summaryDir + '/' + tr.codename
308 core.checkDir(dirname, False)
309 writeTestrunHtml(tr, dirname + '/index.html')
310 for test in summary.allTests():
311 filename = dirname + '/' + testPathToHtmlFilename(test.path)
312 writeResultHtml(test, test.results[j], filename)
314 writefile(os.path.join(summaryDir, 'result.css'), readfile(os.path.join(templatedir, 'result.css')))
315 writefile(os.path.join(summaryDir, 'index.css'), readfile(os.path.join(templatedir, 'index.css')))
316 writeSummaryHtml(summary, summaryDir, 'all')
317 writeSummaryHtml(summary, summaryDir, 'problems')
318 writeSummaryHtml(summary, summaryDir, 'changes')
321 if __name__ == "__main__":
322 main()