VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/webui/wuitestresult.py@ 57761

Last change on this file since 57761 was 56806, checked in by vboxsync, 9 years ago

testmanager/webui: Shorter interval formatting (like for test elapsed time).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 37.2 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuitestresult.py 56806 2015-07-05 16:58:12Z vboxsync $
3
4"""
5Test Manager WUI - Test Results.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2015 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 56806 $"
30
31# Python imports.
32
33# Validation Kit imports.
34from testmanager.webui.wuicontentbase import WuiContentBase, WuiListContentBase, WuiHtmlBase, WuiTmLink, WuiLinkBase, \
35 WuiSvnLink, WuiSvnLinkWithTooltip, WuiBuildLogLink, WuiRawHtml;
36from testmanager.webui.wuimain import WuiMain;
37from testmanager.core.report import ReportGraphModel;
38from testmanager.core.testbox import TestBoxData;
39from testmanager.core.testcase import TestCaseData;
40from testmanager.core.testset import TestSetData;
41from testmanager.core.testgroup import TestGroupData;
42from testmanager.core.build import BuildData;
43from testmanager.core import db;
44from testmanager import config;
45from common import webutils, utils;
46
47
48class WuiTestResult(WuiContentBase):
49 """Display test case result"""
50
51 def __init__(self, fnDPrint = None, oDisp = None):
52 WuiContentBase.__init__(self, fnDPrint = fnDPrint, oDisp = oDisp);
53
54 # Cyclic import hacks.
55 from testmanager.webui.wuiadmin import WuiAdmin;
56 self.oWuiAdmin = WuiAdmin;
57
58 def _toHtml(self, oObject):
59 """Translate some object to HTML."""
60 if isinstance(oObject, WuiHtmlBase):
61 return oObject.toHtml();
62 if db.isDbTimestamp(oObject):
63 return webutils.escapeElem(self.formatTsShort(oObject));
64 if db.isDbInterval(oObject):
65 return webutils.escapeElem(self.formatIntervalShort(oObject));
66 if utils.isString(oObject):
67 return webutils.escapeElem(oObject);
68 return webutils.escapeElem(str(oObject));
69
70 def _htmlTable(self, aoTableContent):
71 """Generate HTML code for table"""
72 sHtml = u' <table class="tmtbl-testresult-details" width="100%%">\n';
73
74 for aoSubRows in aoTableContent:
75 if len(aoSubRows) == 0:
76 continue; # Can happen if there is no testsuit.
77 oCaption = aoSubRows[0];
78 sHtml += u' \n' \
79 u' <tr class="tmtbl-result-details-caption">\n' \
80 u' <td colspan="2">%s</td>\n' \
81 u' </tr>\n' \
82 % (self._toHtml(oCaption),);
83
84 iRow = 0;
85 for aoRow in aoSubRows[1:]:
86 iRow += 1;
87 sHtml += u' <tr class="%s">\n' % ('tmodd' if iRow & 1 else 'tmeven',);
88 if len(aoRow) == 1:
89 sHtml += u' <td class="tmtbl-result-details-subcaption" colspan="2">%s</td>\n' \
90 % (self._toHtml(aoRow[0]),);
91 else:
92 sHtml += u' <th scope="row">%s</th>\n' % (webutils.escapeElem(aoRow[0]),);
93 if len(aoRow) > 2:
94 sHtml += u' <td>%s</td>\n' % (aoRow[2](aoRow[1]),);
95 else:
96 sHtml += u' <td>%s</td>\n' % (self._toHtml(aoRow[1]),);
97 sHtml += u' </tr>\n';
98
99 sHtml += u' </table>\n';
100
101 return sHtml
102
103 def _highlightStatus(self, sStatus):
104 """Return sStatus string surrounded by HTML highlight code """
105 sTmp = '<font color=%s><b>%s</b></font>' \
106 % ('red' if sStatus == 'failure' else 'green', webutils.escapeElem(sStatus.upper()))
107 return sTmp
108
109 def _anchorAndAppendBinaries(self, sBinaries, aoRows):
110 """ Formats each binary (if any) into a row with a download link. """
111 if sBinaries is not None:
112 for sBinary in sBinaries.split(','):
113 if not webutils.hasSchema(sBinary):
114 sBinary = config.g_ksBuildBinUrlPrefix + sBinary;
115 aoRows.append([WuiLinkBase(webutils.getFilename(sBinary), sBinary, fBracketed = False),]);
116 return aoRows;
117
118
119 def _recursivelyGenerateEvents(self, oTestResult, sParentName, sLineage, iRow,
120 iFailure, oTestSet, iDepth): # pylint: disable=R0914
121 """
122 Recursively generate event table rows for the result set.
123
124 oTestResult is an object of the type TestResultDataEx.
125 """
126 # Hack: Replace empty outer test result name with (pretty) command line.
127 if iRow == 1:
128 sName = '';
129 sDisplayName = sParentName;
130 else:
131 sName = oTestResult.sName if sParentName == '' else '%s, %s' % (sParentName, oTestResult.sName,);
132 sDisplayName = webutils.escapeElem(sName);
133
134 # Format error count.
135 sErrCnt = '';
136 if oTestResult.cErrors > 0:
137 sErrCnt = ' (1 error)' if oTestResult.cErrors == 1 else ' (%d errors)' % oTestResult.cErrors;
138
139 # Format the include in graph checkboxes.
140 sLineage += ':%u' % (oTestResult.idStrName,);
141 sResultGraph = '<input type="checkbox" name="%s" value="%s%s" title="Include result in graph."/>' \
142 % (WuiMain.ksParamReportSubjectIds, ReportGraphModel.ksTypeResult, sLineage,);
143 sElapsedGraph = '';
144 if oTestResult.tsElapsed is not None:
145 sElapsedGraph = '<input type="checkbox" name="%s" value="%s%s" title="Include elapsed time in graph."/>' \
146 % ( WuiMain.ksParamReportSubjectIds, ReportGraphModel.ksTypeElapsed, sLineage);
147
148
149 if len(oTestResult.aoChildren) == 0 \
150 and len(oTestResult.aoValues) == 0 \
151 and len(oTestResult.aoMsgs) == 0 \
152 and len(oTestResult.aoFiles) == 0:
153 # Leaf - single row.
154 tsEvent = oTestResult.tsCreated;
155 if oTestResult.tsElapsed is not None:
156 tsEvent += oTestResult.tsElapsed;
157 sHtml = ' <tr class="%s tmtbl-events-leaf tmtbl-events-lvl%s tmstatusrow-%s">\n' \
158 ' <td>%s</td>\n' \
159 ' <td>%s</td>\n' \
160 ' <td>%s</td>\n' \
161 ' <td>%s</td>\n' \
162 ' <td colspan="2"%s>%s%s</td>\n' \
163 ' <td>%s</td>\n' \
164 ' </tr>\n' \
165 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth, oTestResult.enmStatus,
166 webutils.escapeElem(self.formatTsShort(tsEvent)),
167 sElapsedGraph,
168 webutils.escapeElem(self.formatIntervalShort(oTestResult.tsElapsed)) if oTestResult.tsElapsed is not None
169 else '',
170 sDisplayName,
171 ' id="failure-%u"' % (iFailure,) if oTestResult.isFailure() else '',
172 webutils.escapeElem(oTestResult.enmStatus), webutils.escapeElem(sErrCnt),
173 sResultGraph );
174 iRow += 1;
175 else:
176 # Multiple rows.
177 sHtml = ' <tr class="%s tmtbl-events-first tmtbl-events-lvl%s ">\n' \
178 ' <td>%s</td>\n' \
179 ' <td></td>\n' \
180 ' <td></td>\n' \
181 ' <td>%s</td>\n' \
182 ' <td colspan="2">%s</td>\n' \
183 ' <td></td>\n' \
184 ' </tr>\n' \
185 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
186 webutils.escapeElem(self.formatTsShort(oTestResult.tsCreated)), ## @todo more timeline stuff later.
187 sDisplayName,
188 'running' if oTestResult.tsElapsed is None else '', );
189 iRow += 1;
190
191 # Depth.
192 for oChild in oTestResult.aoChildren:
193 (sChildHtml, iRow, iFailure) = self._recursivelyGenerateEvents(oChild, sName, sLineage,
194 iRow, iFailure, oTestSet, iDepth + 1);
195 sHtml += sChildHtml;
196
197
198 # Messages.
199 for oMsg in oTestResult.aoMsgs:
200 sHtml += ' <tr class="%s tmtbl-events-message tmtbl-events-lvl%s">\n' \
201 ' <td>%s</td>\n' \
202 ' <td></td>\n' \
203 ' <td></td>\n' \
204 ' <td colspan="3">%s: %s</td>\n' \
205 ' <td></td>\n' \
206 ' </tr>\n' \
207 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
208 webutils.escapeElem(self.formatTsShort(oMsg.tsCreated)),
209 webutils.escapeElem(oMsg.enmLevel),
210 webutils.escapeElem(oMsg.sMsg), );
211 iRow += 1;
212
213 # Values.
214 for oValue in oTestResult.aoValues:
215 sHtml += ' <tr class="%s tmtbl-events-value tmtbl-events-lvl%s">\n' \
216 ' <td>%s</td>\n' \
217 ' <td></td>\n' \
218 ' <td></td>\n' \
219 ' <td>%s</td>\n' \
220 ' <td class="tmtbl-events-number">%s</td>\n' \
221 ' <td class="tmtbl-events-unit">%s</td>\n' \
222 ' <td><input type="checkbox" name="%s" value="%s%s:%u" title="Include value in graph."></td>\n' \
223 ' </tr>\n' \
224 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
225 webutils.escapeElem(self.formatTsShort(oValue.tsCreated)),
226 webutils.escapeElem(oValue.sName),
227 utils.formatNumber(oValue.lValue).replace(' ', '&nbsp;'),
228 webutils.escapeElem(oValue.sUnit),
229 WuiMain.ksParamReportSubjectIds, ReportGraphModel.ksTypeValue, sLineage, oValue.idStrName, );
230 iRow += 1;
231
232 # Files.
233 for oFile in oTestResult.aoFiles:
234 if oFile.sMime in [ 'text/plain', ]:
235 aoLinks = [
236 WuiTmLink('%s (%s)' % (oFile.sFile, oFile.sKind), '',
237 { self._oDisp.ksParamAction: self._oDisp.ksActionViewLog,
238 self._oDisp.ksParamLogSetId: oTestSet.idTestSet,
239 self._oDisp.ksParamLogFileId: oFile.idTestResultFile, },
240 sTitle = oFile.sDescription),
241 WuiTmLink('View Raw', '',
242 { self._oDisp.ksParamAction: self._oDisp.ksActionGetFile,
243 self._oDisp.ksParamGetFileSetId: oTestSet.idTestSet,
244 self._oDisp.ksParamGetFileId: oFile.idTestResultFile,
245 self._oDisp.ksParamGetFileDownloadIt: False, },
246 sTitle = oFile.sDescription),
247 ]
248 else:
249 aoLinks = [
250 WuiTmLink('%s (%s)' % (oFile.sFile, oFile.sKind), '',
251 { self._oDisp.ksParamAction: self._oDisp.ksActionGetFile,
252 self._oDisp.ksParamGetFileSetId: oTestSet.idTestSet,
253 self._oDisp.ksParamGetFileId: oFile.idTestResultFile,
254 self._oDisp.ksParamGetFileDownloadIt: False, },
255 sTitle = oFile.sDescription),
256 ]
257 aoLinks.append(WuiTmLink('Download', '',
258 { self._oDisp.ksParamAction: self._oDisp.ksActionGetFile,
259 self._oDisp.ksParamGetFileSetId: oTestSet.idTestSet,
260 self._oDisp.ksParamGetFileId: oFile.idTestResultFile,
261 self._oDisp.ksParamGetFileDownloadIt: True, },
262 sTitle = oFile.sDescription));
263
264 sHtml += ' <tr class="%s tmtbl-events-file tmtbl-events-lvl%s">\n' \
265 ' <td></td>\n' \
266 ' <td>%s</td>\n' \
267 ' <td></td>\n' \
268 ' <td>%s</td>\n' \
269 ' <td></td>\n' \
270 ' <td></td>\n' \
271 ' <td></td>\n' \
272 ' </tr>\n' \
273 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
274 webutils.escapeElem(self.formatTsShort(oFile.tsCreated)),
275 '\n'.join(oLink.toHtml() for oLink in aoLinks),);
276 iRow += 1;
277
278 # Done?
279 if oTestResult.tsElapsed is not None:
280 sHtml += ' <tr class="%s tmtbl-events-final tmtbl-events-lvl%s tmstatusrow-%s">\n' \
281 ' <td>%s</td>\n' \
282 ' <td>%s</td>\n' \
283 ' <td>%s</td>\n' \
284 ' <td>%s</td>\n' \
285 ' <td colspan="2"%s>%s%s</td>\n' \
286 ' <td>%s</td>\n' \
287 ' </tr>\n' \
288 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth, oTestResult.enmStatus,
289 webutils.escapeElem(self.formatTsShort(oTestResult.tsCreated + oTestResult.tsElapsed)),
290 sElapsedGraph,
291 webutils.escapeElem(self.formatIntervalShort(oTestResult.tsElapsed)),
292 sDisplayName,
293 ' id="failure-%u"' % (iFailure,) if oTestResult.isFailure() else '',
294 webutils.escapeElem(oTestResult.enmStatus), webutils.escapeElem(sErrCnt),
295 sResultGraph);
296 iRow += 1;
297
298 if oTestResult.isFailure():
299 iFailure += 1;
300
301 return (sHtml, iRow, iFailure);
302
303 def showTestCaseResultDetails(self, # pylint: disable=R0914,R0915
304 oTestResultTree,
305 oTestSet,
306 oBuildEx,
307 oValidationKitEx,
308 oTestBox,
309 oTestGroup,
310 oTestCaseEx,
311 oTestVarEx):
312 """Show detailed result"""
313 def getTcDepsHtmlList(aoTestCaseData):
314 """Get HTML <ul> list of Test Case name items"""
315 if len(aoTestCaseData) > 0:
316 sTmp = '<ul>'
317 for oTestCaseData in aoTestCaseData:
318 sTmp += '<li>%s</li>' % (webutils.escapeElem(oTestCaseData.sName),);
319 sTmp += '</ul>'
320 else:
321 sTmp = 'No items'
322 return sTmp
323
324 def getGrDepsHtmlList(aoGlobalResourceData):
325 """Get HTML <ul> list of Global Resource name items"""
326 if len(aoGlobalResourceData) > 0:
327 sTmp = '<ul>'
328 for oGlobalResourceData in aoGlobalResourceData:
329 sTmp += '<li>%s</li>' % (webutils.escapeElem(oGlobalResourceData.sName),);
330 sTmp += '</ul>'
331 else:
332 sTmp = 'No items'
333 return sTmp
334
335
336 asHtml = []
337
338 # Test result + test set details.
339 aoResultRows = [
340 WuiTmLink(oTestCaseEx.sName, self.oWuiAdmin.ksScriptName,
341 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionTestCaseDetails,
342 TestCaseData.ksParam_idTestCase: oTestCaseEx.idTestCase,
343 self.oWuiAdmin.ksParamEffectiveDate: oTestSet.tsConfig, },
344 fBracketed = False),
345 ];
346 if oTestCaseEx.sDescription is not None and len(oTestCaseEx.sDescription) > 0:
347 aoResultRows.append([oTestCaseEx.sDescription,]);
348 aoResultRows.append([ 'Status:', WuiRawHtml('<span class="tmspan-status-%s">%s</span>'
349 % (oTestResultTree.enmStatus, oTestResultTree.enmStatus,))]);
350 if oTestResultTree.cErrors > 0:
351 aoResultRows.append(( 'Errors:', oTestResultTree.cErrors ));
352 aoResultRows.append([ 'Elapsed:', oTestResultTree.tsElapsed ]);
353 cSecCfgTimeout = oTestCaseEx.cSecTimeout if oTestVarEx.cSecTimeout is None else oTestVarEx.cSecTimeout;
354 cSecEffTimeout = cSecCfgTimeout * oTestBox.pctScaleTimeout / 100;
355 aoResultRows.append([ 'Timeout:',
356 '%s (%s sec)' % (utils.formatIntervalSeconds(cSecEffTimeout), cSecEffTimeout,) ]);
357 if cSecEffTimeout != cSecCfgTimeout:
358 aoResultRows.append([ 'Cfg Timeout:',
359 '%s (%s sec)' % (utils.formatIntervalSeconds(cSecCfgTimeout), cSecCfgTimeout,) ]);
360 aoResultRows += [
361 ( 'Started:', WuiTmLink(self.formatTsShort(oTestSet.tsCreated), WuiMain.ksScriptName,
362 { WuiMain.ksParamAction: WuiMain.ksActionResultsUnGrouped,
363 WuiMain.ksParamEffectiveDate: oTestSet.tsCreated, },
364 fBracketed = False) ),
365 ];
366 if oTestSet.tsDone is not None:
367 aoResultRows += [ ( 'Done:',
368 WuiTmLink(self.formatTsShort(oTestSet.tsDone), WuiMain.ksScriptName,
369 { WuiMain.ksParamAction: WuiMain.ksActionResultsUnGrouped,
370 WuiMain.ksParamEffectiveDate: oTestSet.tsDone, },
371 fBracketed = False) ) ];
372 else:
373 aoResultRows += [( 'Done:', 'Still running...')];
374 aoResultRows += [( 'Config:', oTestSet.tsConfig )];
375 if oTestVarEx.cGangMembers > 1:
376 aoResultRows.append([ 'Member No:', '#%s (of %s)' % (oTestSet.iGangMemberNo, oTestVarEx.cGangMembers) ]);
377
378 aoResultRows += [
379 ( 'Test Group:', WuiTmLink(oTestGroup.sName, self.oWuiAdmin.ksScriptName,
380 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionTestGroupDetails,
381 TestGroupData.ksParam_idTestGroup: oTestGroup.idTestGroup,
382 self.oWuiAdmin.ksParamEffectiveDate: oTestSet.tsConfig, },
383 fBracketed = False) ),
384 ];
385 if oTestVarEx.sTestBoxReqExpr is not None:
386 aoResultRows.append([ 'TestBox reqs:', oTestVarEx.sTestBoxReqExpr ]);
387 elif oTestCaseEx.sTestBoxReqExpr is not None or oTestVarEx.sTestBoxReqExpr is not None:
388 aoResultRows.append([ 'TestBox reqs:', oTestCaseEx.sTestBoxReqExpr ]);
389 if oTestVarEx.sBuildReqExpr is not None:
390 aoResultRows.append([ 'Build reqs:', oTestVarEx.sBuildReqExpr ]);
391 elif oTestCaseEx.sBuildReqExpr is not None or oTestVarEx.sBuildReqExpr is not None:
392 aoResultRows.append([ 'Build reqs:', oTestCaseEx.sBuildReqExpr ]);
393 if oTestCaseEx.sValidationKitZips is not None and oTestCaseEx.sValidationKitZips != '@VALIDATIONKIT_ZIP@':
394 aoResultRows.append([ 'Validation Kit:', oTestCaseEx.sValidationKitZips ]);
395 if oTestCaseEx.aoDepTestCases is not None and len(oTestCaseEx.aoDepTestCases) > 0:
396 aoResultRows.append([ 'Prereq. Test Cases:', oTestCaseEx.aoDepTestCases, getTcDepsHtmlList ]);
397 if oTestCaseEx.aoDepGlobalResources is not None and len(oTestCaseEx.aoDepGlobalResources) > 0:
398 aoResultRows.append([ 'Global Resources:', oTestCaseEx.aoDepGlobalResources, getGrDepsHtmlList ]);
399
400 # Builds.
401 aoBuildRows = [];
402 if oBuildEx is not None:
403 aoBuildRows += [
404 WuiTmLink('Build', self.oWuiAdmin.ksScriptName,
405 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionBuildDetails,
406 BuildData.ksParam_idBuild: oBuildEx.idBuild,
407 self.oWuiAdmin.ksParamEffectiveDate: oTestSet.tsCreated, },
408 fBracketed = False),
409 ];
410 self._anchorAndAppendBinaries(oBuildEx.sBinaries, aoBuildRows);
411 aoBuildRows += [
412 ( 'Revision:', WuiSvnLinkWithTooltip(oBuildEx.iRevision, oBuildEx.oCat.sRepository,
413 fBracketed = False) ),
414 ( 'Product:', oBuildEx.oCat.sProduct ),
415 ( 'Branch:', oBuildEx.oCat.sBranch ),
416 ( 'Type:', oBuildEx.oCat.sType ),
417 ( 'Version:', oBuildEx.sVersion ),
418 ( 'Created:', oBuildEx.tsCreated ),
419 ];
420 if oBuildEx.uidAuthor is not None:
421 aoBuildRows += [ ( 'Author ID:', oBuildEx.uidAuthor ), ];
422 if oBuildEx.sLogUrl is not None:
423 aoBuildRows += [ ( 'Log:', WuiBuildLogLink(oBuildEx.sLogUrl, fBracketed = False) ), ];
424
425 aoValidationKitRows = [];
426 if oValidationKitEx is not None:
427 aoValidationKitRows += [
428 WuiTmLink('Validation Kit', self.oWuiAdmin.ksScriptName,
429 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionBuildDetails,
430 BuildData.ksParam_idBuild: oValidationKitEx.idBuild,
431 self.oWuiAdmin.ksParamEffectiveDate: oTestSet.tsCreated, },
432 fBracketed = False),
433 ];
434 self._anchorAndAppendBinaries(oValidationKitEx.sBinaries, aoValidationKitRows);
435 aoValidationKitRows += [ ( 'Revision:', WuiSvnLink(oValidationKitEx.iRevision, fBracketed = False) ) ];
436 if oValidationKitEx.oCat.sProduct != 'VBox TestSuite':
437 aoValidationKitRows += [ ( 'Product:', oValidationKitEx.oCat.sProduct ), ];
438 if oValidationKitEx.oCat.sBranch != 'trunk':
439 aoValidationKitRows += [ ( 'Product:', oValidationKitEx.oCat.sBranch ), ];
440 if oValidationKitEx.oCat.sType != 'release':
441 aoValidationKitRows += [ ( 'Type:', oValidationKitEx.oCat.sType), ];
442 if oValidationKitEx.sVersion != '0.0.0':
443 aoValidationKitRows += [ ( 'Version:', oValidationKitEx.sVersion ), ];
444 aoValidationKitRows += [
445 ( 'Created:', oValidationKitEx.tsCreated ),
446 ];
447 if oValidationKitEx.uidAuthor is not None:
448 aoValidationKitRows += [ ( 'Author ID:', oValidationKitEx.uidAuthor ), ];
449 if oValidationKitEx.sLogUrl is not None:
450 aoValidationKitRows += [ ( 'Log:', WuiBuildLogLink(oValidationKitEx.sLogUrl, fBracketed = False) ), ];
451
452 # TestBox.
453 aoTestBoxRows = [
454 WuiTmLink(oTestBox.sName, self.oWuiAdmin.ksScriptName,
455 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionTestBoxDetails,
456 TestBoxData.ksParam_idGenTestBox: oTestSet.idGenTestBox, },
457 fBracketed = False),
458 ];
459 if oTestBox.sDescription is not None and len(oTestBox.sDescription) > 0:
460 aoTestBoxRows.append([oTestBox.sDescription, ]);
461 aoTestBoxRows += [
462 ( 'IP:', oTestBox.ip ),
463 #( 'UUID:', oTestBox.uuidSystem ),
464 #( 'Enabled:', oTestBox.fEnabled ),
465 #( 'Lom Kind:', oTestBox.enmLomKind ),
466 #( 'Lom IP:', oTestBox.ipLom ),
467 ( 'OS/Arch:', '%s.%s' % (oTestBox.sOs, oTestBox.sCpuArch) ),
468 ( 'OS Version:', oTestBox.sOsVersion ),
469 ( 'CPUs:', oTestBox.cCpus ),
470 ];
471 if oTestBox.sCpuName is not None:
472 aoTestBoxRows.append(['CPU Name', oTestBox.sCpuName.replace(' ', ' ')]);
473 if oTestBox.lCpuRevision is not None:
474 # ASSUMING x86+AMD64 versioning scheme here.
475 uFamily = (oTestBox.lCpuRevision >> 24) & 0xff;
476 uModel = (oTestBox.lCpuRevision >> 8) & 0xffff;
477 uStepping = oTestBox.lCpuRevision & 0xff;
478 aoTestBoxRows += [
479 ( 'CPU Family', '%u (%#x)' % ( uFamily, uFamily, ) ),
480 ( 'CPU Model', '%u (%#x)' % ( uModel, uModel, ) ),
481 ( 'CPU Stepping', '%u (%#x)' % ( uStepping, uStepping, ) ),
482 ];
483 asFeatures = [ oTestBox.sCpuVendor, ];
484 if oTestBox.fCpuHwVirt is True: asFeatures.append(u'HW\u2011Virt');
485 if oTestBox.fCpuNestedPaging is True: asFeatures.append(u'Nested\u2011Paging');
486 if oTestBox.fCpu64BitGuest is True: asFeatures.append(u'64\u2011bit\u2011Guest');
487 if oTestBox.fChipsetIoMmu is True: asFeatures.append(u'I/O\u2011MMU');
488 aoTestBoxRows += [
489 ( 'Features:', u' '.join(asFeatures) ),
490 ( 'RAM size:', '%s MB' % (oTestBox.cMbMemory,) ),
491 ( 'Scratch Size:', '%s MB' % (oTestBox.cMbScratch,) ),
492 ( 'Scale Timeout:', '%s%%' % (oTestBox.pctScaleTimeout,) ),
493 ( 'Script Rev:', WuiSvnLink(oTestBox.iTestBoxScriptRev, fBracketed = False) ),
494 ( 'Python:', oTestBox.formatPythonVersion() ),
495 ( 'Pending Command:', oTestBox.enmPendingCmd ),
496 ];
497
498 aoRows = [
499 aoResultRows,
500 aoBuildRows,
501 aoValidationKitRows,
502 aoTestBoxRows,
503 ];
504
505 asHtml.append(self._htmlTable(aoRows));
506
507 #
508 # Convert the tree to a list of events, values, message and files.
509 #
510 sHtmlEvents = '';
511 sHtmlEvents += '<table class="tmtbl-events" id="tmtbl-events" width="100%">\n';
512 sHtmlEvents += ' <tr class="tmheader">\n' \
513 ' <th>When</th>\n' \
514 ' <th></th>\n' \
515 ' <th>Elapsed</th>\n' \
516 ' <th>Event name</th>\n' \
517 ' <th colspan="2">Value (status)</th>' \
518 ' <th></th>\n' \
519 ' </tr>\n';
520 sPrettyCmdLine = '&nbsp;\\<br>&nbsp;&nbsp;&nbsp;&nbsp;\n'.join(webutils.escapeElem(oTestCaseEx.sBaseCmd
521 + ' '
522 + oTestVarEx.sArgs).split() );
523 (sTmp, _, cFailures) = self._recursivelyGenerateEvents(oTestResultTree, sPrettyCmdLine, '', 1, 0, oTestSet, 0);
524 sHtmlEvents += sTmp;
525
526 sHtmlEvents += '</table>\n'
527
528 #
529 # Put it all together.
530 #
531 sHtml = '<table class="tmtbl-testresult-details-base" width="100%">\n';
532 sHtml += ' <tr>\n'
533 sHtml += ' <td valign="top" width="20%%">\n%s\n</td>\n' % ' <br>\n'.join(asHtml);
534
535 sHtml += ' <td valign="top" width="80%" style="padding-left:6px">\n';
536 sHtml += ' <h2>Events:</h2>\n';
537 sHtml += ' <form action="#" method="get" id="graph-form">\n' \
538 ' <input type="hidden" name="%s" value="%s"/>\n' \
539 ' <input type="hidden" name="%s" value="%u"/>\n' \
540 ' <input type="hidden" name="%s" value="%u"/>\n' \
541 ' <input type="hidden" name="%s" value="%u"/>\n' \
542 ' <input type="hidden" name="%s" value="%u"/>\n' \
543 % ( WuiMain.ksParamAction, WuiMain.ksActionGraphWiz,
544 WuiMain.ksParamGraphWizTestBoxIds, oTestBox.idTestBox,
545 WuiMain.ksParamGraphWizBuildCatIds, oBuildEx.idBuildCategory,
546 WuiMain.ksParamGraphWizTestCaseIds, oTestSet.idTestCase,
547 WuiMain.ksParamGraphWizSrcTestSetId, oTestSet.idTestSet,
548 );
549 if oTestSet.tsDone is not None:
550 sHtml += ' <input type="hidden" name="%s" value="%s"/>\n' \
551 % ( WuiMain.ksParamEffectiveDate, oTestSet.tsDone, );
552 sHtml += ' <p>\n';
553 sFormButton = '<button type="submit" onclick="%s">Show graphs</button>' \
554 % ( webutils.escapeAttr('addDynamicGraphInputs("graph-form", "main", "%s", "%s");'
555 % (WuiMain.ksParamGraphWizWidth, WuiMain.ksParamGraphWizDpi, )) );
556 sHtml += ' ' + sFormButton + '\n';
557 sHtml += ' %s %s %s\n' \
558 % ( WuiTmLink('Log File', '',
559 { WuiMain.ksParamAction: WuiMain.ksActionViewLog,
560 WuiMain.ksParamLogSetId: oTestSet.idTestSet,
561 }),
562 WuiTmLink('Raw Log', '',
563 { WuiMain.ksParamAction: WuiMain.ksActionGetFile,
564 WuiMain.ksParamGetFileSetId: oTestSet.idTestSet,
565 WuiMain.ksParamGetFileDownloadIt: False,
566 }),
567 WuiTmLink('Download Log', '',
568 { WuiMain.ksParamAction: WuiMain.ksActionGetFile,
569 WuiMain.ksParamGetFileSetId: oTestSet.idTestSet,
570 WuiMain.ksParamGetFileDownloadIt: True,
571 }),
572 );
573 sHtml += ' </p>\n';
574 if cFailures == 1:
575 sHtml += ' <p>%s</p>\n' % ( WuiTmLink('Jump to failure', '#failure-0'), )
576 elif cFailures > 1:
577 sHtml += ' <p>Jump to failure: ';
578 if cFailures <= 13:
579 for iFailure in range(0, cFailures):
580 sHtml += ' ' + WuiTmLink('#%u' % (iFailure,), '#failure-%u' % (iFailure,)).toHtml();
581 else:
582 for iFailure in range(0, 6):
583 sHtml += ' ' + WuiTmLink('#%u' % (iFailure,), '#failure-%u' % (iFailure,)).toHtml();
584 sHtml += ' ... ';
585 for iFailure in range(cFailures - 6, cFailures):
586 sHtml += ' ' + WuiTmLink('#%u' % (iFailure,), '#failure-%u' % (iFailure,)).toHtml();
587 sHtml += ' </p>\n';
588
589 sHtml += sHtmlEvents;
590 sHtml += ' <p>' + sFormButton + '</p>\n';
591 sHtml += ' </form>\n';
592 sHtml += ' </td>\n';
593
594 sHtml += ' </tr>\n';
595 sHtml += '</table>\n';
596
597 return ('Test Case result details', sHtml)
598
599
600class WuiGroupedResultList(WuiListContentBase):
601 """
602 WUI results content generator.
603 """
604
605 def __init__(self, aoEntries, cEntriesCount, iPage, cItemsPerPage, tsEffective, fnDPrint, oDisp):
606 """Override initialization"""
607 WuiListContentBase.__init__(self, aoEntries, iPage, cItemsPerPage, tsEffective,
608 sTitle = 'Ungrouped (%d)' % cEntriesCount, sId = 'results',
609 fnDPrint = fnDPrint, oDisp = oDisp);
610
611 self._cEntriesCount = cEntriesCount
612
613 self._asColumnHeaders = [
614 'Start',
615 'Product Build',
616 'Validation Kit',
617 'TestBox OS',
618 'TestBox Name',
619 'Test Case',
620 'Elapsed',
621 'Result',
622 ];
623 self._asColumnAttribs = ['align="center"', 'align="center"', 'align="center"',
624 'align="center"', 'align="center"', 'align="center"',
625 'align="center"', 'align="center"', 'align="center"',
626 'align="center"', 'align="center"', 'align="center"' ]
627
628
629 # Prepare parameter lists.
630 self._dTestBoxLinkParams = self._oDisp.getParameters();
631 self._dTestBoxLinkParams[WuiMain.ksParamAction] = WuiMain.ksActionResultsGroupedByTestBox;
632
633 self._dTestCaseLinkParams = self._oDisp.getParameters();
634 self._dTestCaseLinkParams[WuiMain.ksParamAction] = WuiMain.ksActionResultsGroupedByTestCase;
635
636 self._dRevLinkParams = self._oDisp.getParameters();
637 self._dRevLinkParams[WuiMain.ksParamAction] = WuiMain.ksActionResultsGroupedByBuildRev;
638
639
640
641 def _formatListEntry(self, iEntry):
642 """
643 Format *show all* table entry
644 """
645 oEntry = self._aoEntries[iEntry];
646
647 from testmanager.webui.wuiadmin import WuiAdmin;
648
649
650 oValidationKit = None;
651 if oEntry.idBuildTestSuite is not None:
652 oValidationKit = WuiTmLink('#%d - r%s' % (oEntry.idBuildTestSuite, oEntry.iRevisionTestSuite),
653 WuiAdmin.ksScriptName,
654 { WuiAdmin.ksParamAction: WuiAdmin.ksActionBuildDetails,
655 BuildData.ksParam_idBuild: oEntry.idBuildTestSuite },
656 fBracketed = False);
657
658
659 aoTestSetLinks = [ WuiTmLink(oEntry.enmStatus,
660 WuiMain.ksScriptName,
661 { WuiMain.ksParamAction: WuiMain.ksActionTestResultDetails,
662 TestSetData.ksParam_idTestSet: oEntry.idTestSet },
663 fBracketed = False),];
664 if oEntry.cErrors > 0:
665 aoTestSetLinks.append(WuiTmLink('- %d error(s)' % (oEntry.cErrors, ),
666 WuiMain.ksScriptName,
667 { WuiMain.ksParamAction: WuiMain.ksActionTestResultDetails,
668 TestSetData.ksParam_idTestSet: oEntry.idTestSet },
669 sFragmentId = 'failure-0', fBracketed = False));
670
671
672 self._dTestBoxLinkParams[WuiMain.ksParamGroupMemberId] = oEntry.idTestBox;
673 self._dTestCaseLinkParams[WuiMain.ksParamGroupMemberId] = oEntry.idTestCase;
674 self._dRevLinkParams[WuiMain.ksParamGroupMemberId] = oEntry.iRevision;
675
676 sTestBoxTitle = u'';
677 if oEntry.sCpuVendor is not None:
678 sTestBoxTitle += 'CPU vendor:\t%s\n' % ( oEntry.sCpuVendor, );
679 if oEntry.sCpuName is not None:
680 sTestBoxTitle += 'CPU name:\t%s\n' % ( ' '.join(oEntry.sCpuName.split()), );
681 if oEntry.sOsVersion is not None:
682 sTestBoxTitle += 'OS version:\t%s\n' % ( oEntry.sOsVersion, );
683 asFeatures = [];
684 if oEntry.fCpuHwVirt is True: asFeatures.append(u'HW\u2011Virt');
685 if oEntry.fCpuNestedPaging is True: asFeatures.append(u'Nested\u2011Paging');
686 if oEntry.fCpu64BitGuest is True: asFeatures.append(u'64\u2011bit\u2011Guest');
687 #if oEntry.fChipsetIoMmu is True: asFeatures.append(u'I/O\u2011MMU');
688 sTestBoxTitle += u'CPU features:\t' + u', '.join(asFeatures);
689
690 return [
691 oEntry.tsCreated,
692 [ WuiTmLink('#%d - %s %s (%s)' % (oEntry.idBuild, oEntry.sProduct, oEntry.sVersion, oEntry.sType,),
693 WuiMain.ksScriptName, self._dRevLinkParams, sTitle = '%s' % (oEntry.sBranch,), fBracketed = False),
694 WuiSvnLinkWithTooltip(oEntry.iRevision, 'vbox'), ## @todo add sRepository TestResultListingData
695 WuiTmLink(self.ksShortDetailsLink, WuiAdmin.ksScriptName,
696 { WuiAdmin.ksParamAction: WuiAdmin.ksActionBuildDetails,
697 BuildData.ksParam_idBuild: oEntry.idBuild },
698 fBracketed = False),
699 ],
700 oValidationKit,
701 '%s.%s' % (oEntry.sOs, oEntry.sArch),
702 [ WuiTmLink(oEntry.sTestBoxName, WuiMain.ksScriptName, self._dTestBoxLinkParams, fBracketed = False,
703 sTitle = sTestBoxTitle),
704 WuiTmLink(self.ksShortDetailsLink, WuiAdmin.ksScriptName,
705 { WuiAdmin.ksParamAction: WuiAdmin.ksActionTestBoxDetails,
706 TestBoxData.ksParam_idTestBox: oEntry.idTestBox },
707 fBracketed = False) ],
708 [ WuiTmLink(oEntry.sTestCaseName, WuiMain.ksScriptName, self._dTestCaseLinkParams, fBracketed = False,
709 sTitle = (oEntry.sBaseCmd + ' ' + oEntry.sArgs) if oEntry.sArgs else oEntry.sBaseCmd),
710 WuiTmLink(self.ksShortDetailsLink, WuiAdmin.ksScriptName,
711 { WuiAdmin.ksParamAction: WuiAdmin.ksActionTestCaseDetails,
712 TestCaseData.ksParam_idTestCase: oEntry.idTestCase },
713 fBracketed = False), ],
714 oEntry.tsElapsed,
715 aoTestSetLinks
716 ];
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette