VirtualBox

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

Last change on this file since 88839 was 83403, checked in by vboxsync, 5 years ago

TestManager/webui: Better/generic testbox links.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 52.1 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuitestresult.py 83403 2020-03-25 12:09:58Z vboxsync $
3
4"""
5Test Manager WUI - Test Results.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2020 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: 83403 $"
30
31# Python imports.
32import datetime;
33
34# Validation Kit imports.
35from testmanager.webui.wuicontentbase import WuiContentBase, WuiListContentBase, WuiHtmlBase, WuiTmLink, WuiLinkBase, \
36 WuiSvnLink, WuiSvnLinkWithTooltip, WuiBuildLogLink, WuiRawHtml, \
37 WuiHtmlKeeper;
38from testmanager.webui.wuimain import WuiMain;
39from testmanager.webui.wuihlpform import WuiHlpForm;
40from testmanager.webui.wuiadminfailurereason import WuiFailureReasonAddLink, WuiFailureReasonDetailsLink;
41from testmanager.webui.wuitestresultfailure import WuiTestResultFailureDetailsLink;
42from testmanager.core.failurereason import FailureReasonData, FailureReasonLogic;
43from testmanager.core.report import ReportGraphModel, ReportModelBase;
44from testmanager.core.testbox import TestBoxData;
45from testmanager.core.testcase import TestCaseData;
46from testmanager.core.testset import TestSetData;
47from testmanager.core.testgroup import TestGroupData;
48from testmanager.core.testresultfailures import TestResultFailureData;
49from testmanager.core.build import BuildData;
50from testmanager.core import db;
51from testmanager import config;
52from common import webutils, utils;
53
54
55class WuiTestSetLink(WuiTmLink):
56 """ Test set link. """
57
58 def __init__(self, idTestSet, sName = WuiContentBase.ksShortDetailsLink, fBracketed = False):
59 WuiTmLink.__init__(self, sName, WuiMain.ksScriptName,
60 { WuiMain.ksParamAction: WuiMain.ksActionTestResultDetails,
61 TestSetData.ksParam_idTestSet: idTestSet, }, fBracketed = fBracketed);
62 self.idTestSet = idTestSet;
63
64class WuiTestResultsForSomethingLink(WuiTmLink):
65 """ Test results link for a grouping. """
66
67 def __init__(self, sGroupedBy, idGroupMember, sName = WuiContentBase.ksShortTestResultsLink,
68 dExtraParams = None, fBracketed = False):
69 dParams = dict(dExtraParams) if dExtraParams else dict();
70 dParams[WuiMain.ksParamAction] = sGroupedBy;
71 dParams[WuiMain.ksParamGroupMemberId] = idGroupMember;
72 WuiTmLink.__init__(self, sName, WuiMain.ksScriptName, dParams, fBracketed = fBracketed);
73
74
75class WuiTestResultsForTestBoxLink(WuiTestResultsForSomethingLink):
76 """ Test results link for a given testbox. """
77
78 def __init__(self, idTestBox, sName = WuiContentBase.ksShortTestResultsLink, dExtraParams = None, fBracketed = False):
79 WuiTestResultsForSomethingLink.__init__(self, WuiMain.ksActionResultsGroupedByTestBox, idTestBox,
80 sName = sName, dExtraParams = dExtraParams, fBracketed = fBracketed);
81
82
83class WuiTestResultsForTestCaseLink(WuiTestResultsForSomethingLink):
84 """ Test results link for a given testcase. """
85
86 def __init__(self, idTestCase, sName = WuiContentBase.ksShortTestResultsLink, dExtraParams = None, fBracketed = False):
87 WuiTestResultsForSomethingLink.__init__(self, WuiMain.ksActionResultsGroupedByTestCase, idTestCase,
88 sName = sName, dExtraParams = dExtraParams, fBracketed = fBracketed);
89
90
91class WuiTestResultsForBuildRevLink(WuiTestResultsForSomethingLink):
92 """ Test results link for a given build revision. """
93
94 def __init__(self, iRevision, sName = WuiContentBase.ksShortTestResultsLink, dExtraParams = None, fBracketed = False):
95 WuiTestResultsForSomethingLink.__init__(self, WuiMain.ksActionResultsGroupedByBuildRev, iRevision,
96 sName = sName, dExtraParams = dExtraParams, fBracketed = fBracketed);
97
98
99class WuiTestResult(WuiContentBase):
100 """Display test case result"""
101
102 def __init__(self, fnDPrint = None, oDisp = None):
103 WuiContentBase.__init__(self, fnDPrint = fnDPrint, oDisp = oDisp);
104
105 # Cyclic import hacks.
106 from testmanager.webui.wuiadmin import WuiAdmin;
107 self.oWuiAdmin = WuiAdmin;
108
109 def _toHtml(self, oObject):
110 """Translate some object to HTML."""
111 if isinstance(oObject, WuiHtmlBase):
112 return oObject.toHtml();
113 if db.isDbTimestamp(oObject):
114 return webutils.escapeElem(self.formatTsShort(oObject));
115 if db.isDbInterval(oObject):
116 return webutils.escapeElem(self.formatIntervalShort(oObject));
117 if utils.isString(oObject):
118 return webutils.escapeElem(oObject);
119 return webutils.escapeElem(str(oObject));
120
121 def _htmlTable(self, aoTableContent):
122 """Generate HTML code for table"""
123 sHtml = u' <table class="tmtbl-testresult-details" width="100%%">\n';
124
125 for aoSubRows in aoTableContent:
126 if not aoSubRows:
127 continue; # Can happen if there is no testsuit.
128 oCaption = aoSubRows[0];
129 sHtml += u' \n' \
130 u' <tr class="tmtbl-result-details-caption">\n' \
131 u' <td colspan="2">%s</td>\n' \
132 u' </tr>\n' \
133 % (self._toHtml(oCaption),);
134
135 iRow = 0;
136 for aoRow in aoSubRows[1:]:
137 iRow += 1;
138 sHtml += u' <tr class="%s">\n' % ('tmodd' if iRow & 1 else 'tmeven',);
139 if len(aoRow) == 1:
140 sHtml += u' <td class="tmtbl-result-details-subcaption" colspan="2">%s</td>\n' \
141 % (self._toHtml(aoRow[0]),);
142 else:
143 sHtml += u' <th scope="row">%s</th>\n' % (webutils.escapeElem(aoRow[0]),);
144 if len(aoRow) > 2:
145 sHtml += u' <td>%s</td>\n' % (aoRow[2](aoRow[1]),);
146 else:
147 sHtml += u' <td>%s</td>\n' % (self._toHtml(aoRow[1]),);
148 sHtml += u' </tr>\n';
149
150 sHtml += u' </table>\n';
151
152 return sHtml
153
154 def _highlightStatus(self, sStatus):
155 """Return sStatus string surrounded by HTML highlight code """
156 sTmp = '<font color=%s><b>%s</b></font>' \
157 % ('red' if sStatus == 'failure' else 'green', webutils.escapeElem(sStatus.upper()))
158 return sTmp
159
160 def _anchorAndAppendBinaries(self, sBinaries, aoRows):
161 """ Formats each binary (if any) into a row with a download link. """
162 if sBinaries is not None:
163 for sBinary in sBinaries.split(','):
164 if not webutils.hasSchema(sBinary):
165 sBinary = config.g_ksBuildBinUrlPrefix + sBinary;
166 aoRows.append([WuiLinkBase(webutils.getFilename(sBinary), sBinary, fBracketed = False),]);
167 return aoRows;
168
169
170 def _formatEventTimestampHtml(self, tsEvent, tsLog, idEvent, oTestSet):
171 """ Formats an event timestamp with a main log link. """
172 tsEvent = db.dbTimestampToZuluDatetime(tsEvent);
173 #sFormattedTimestamp = u'%04u\u2011%02u\u2011%02u\u00a0%02u:%02u:%02uZ' \
174 # % ( tsEvent.year, tsEvent.month, tsEvent.day,
175 # tsEvent.hour, tsEvent.minute, tsEvent.second,);
176 sFormattedTimestamp = u'%02u:%02u:%02uZ' \
177 % ( tsEvent.hour, tsEvent.minute, tsEvent.second,);
178 sTitle = u'#%u - %04u\u2011%02u\u2011%02u\u00a0%02u:%02u:%02u.%06uZ' \
179 % ( idEvent, tsEvent.year, tsEvent.month, tsEvent.day,
180 tsEvent.hour, tsEvent.minute, tsEvent.second, tsEvent.microsecond, );
181 tsLog = db.dbTimestampToZuluDatetime(tsLog);
182 sFragment = u'%02u_%02u_%02u_%06u' % ( tsLog.hour, tsLog.minute, tsLog.second, tsLog.microsecond);
183 return WuiTmLink(sFormattedTimestamp, '',
184 { WuiMain.ksParamAction: WuiMain.ksActionViewLog,
185 WuiMain.ksParamLogSetId: oTestSet.idTestSet, },
186 sFragmentId = sFragment, sTitle = sTitle, fBracketed = False, ).toHtml();
187
188 def _recursivelyGenerateEvents(self, oTestResult, sParentName, sLineage, iRow,
189 iFailure, oTestSet, iDepth): # pylint: disable=too-many-locals
190 """
191 Recursively generate event table rows for the result set.
192
193 oTestResult is an object of the type TestResultDataEx.
194 """
195 # Hack: Replace empty outer test result name with (pretty) command line.
196 if iRow == 1:
197 sName = '';
198 sDisplayName = sParentName;
199 else:
200 sName = oTestResult.sName if sParentName == '' else '%s, %s' % (sParentName, oTestResult.sName,);
201 sDisplayName = webutils.escapeElem(sName);
202
203 # Format error count.
204 sErrCnt = '';
205 if oTestResult.cErrors > 0:
206 sErrCnt = ' (1 error)' if oTestResult.cErrors == 1 else ' (%d errors)' % oTestResult.cErrors;
207
208 # Format bits for adding or editing the failure reason. Level 0 is handled at the top of the page.
209 sChangeReason = '';
210 if oTestResult.cErrors > 0 and iDepth > 0 and self._oDisp is not None and not self._oDisp.isReadOnlyUser():
211 dTmp = {
212 self._oDisp.ksParamAction: self._oDisp.ksActionTestResultFailureAdd if oTestResult.oReason is None else
213 self._oDisp.ksActionTestResultFailureEdit,
214 TestResultFailureData.ksParam_idTestResult: oTestResult.idTestResult,
215 };
216 sChangeReason = ' <a href="?%s" class="tmtbl-edit-reason" onclick="addRedirectToAnchorHref(this)">%s</a> ' \
217 % ( webutils.encodeUrlParams(dTmp), WuiContentBase.ksShortEditLinkHtml );
218
219 # Format the include in graph checkboxes.
220 sLineage += ':%u' % (oTestResult.idStrName,);
221 sResultGraph = '<input type="checkbox" name="%s" value="%s%s" title="Include result in graph."/>' \
222 % (WuiMain.ksParamReportSubjectIds, ReportGraphModel.ksTypeResult, sLineage,);
223 sElapsedGraph = '';
224 if oTestResult.tsElapsed is not None:
225 sElapsedGraph = '<input type="checkbox" name="%s" value="%s%s" title="Include elapsed time in graph."/>' \
226 % ( WuiMain.ksParamReportSubjectIds, ReportGraphModel.ksTypeElapsed, sLineage);
227
228
229 if not oTestResult.aoChildren \
230 and len(oTestResult.aoValues) + len(oTestResult.aoMsgs) + len(oTestResult.aoFiles) == 0:
231 # Leaf - single row.
232 tsEvent = oTestResult.tsCreated;
233 if oTestResult.tsElapsed is not None:
234 tsEvent += oTestResult.tsElapsed;
235 sHtml = ' <tr class="%s tmtbl-events-leaf tmtbl-events-lvl%s tmstatusrow-%s" id="S%u">\n' \
236 ' <td id="E%u">%s</td>\n' \
237 ' <td>%s</td>\n' \
238 ' <td>%s</td>\n' \
239 ' <td>%s</td>\n' \
240 ' <td colspan="2"%s>%s%s%s</td>\n' \
241 ' <td>%s</td>\n' \
242 ' </tr>\n' \
243 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth, oTestResult.enmStatus, oTestResult.idTestResult,
244 oTestResult.idTestResult,
245 self._formatEventTimestampHtml(tsEvent, oTestResult.tsCreated, oTestResult.idTestResult, oTestSet),
246 sElapsedGraph,
247 webutils.escapeElem(self.formatIntervalShort(oTestResult.tsElapsed)) if oTestResult.tsElapsed is not None
248 else '',
249 sDisplayName,
250 ' id="failure-%u"' % (iFailure,) if oTestResult.isFailure() else '',
251 webutils.escapeElem(oTestResult.enmStatus), webutils.escapeElem(sErrCnt),
252 sChangeReason if oTestResult.oReason is None else '',
253 sResultGraph );
254 iRow += 1;
255 else:
256 # Multiple rows.
257 sHtml = ' <tr class="%s tmtbl-events-first tmtbl-events-lvl%s ">\n' \
258 ' <td>%s</td>\n' \
259 ' <td></td>\n' \
260 ' <td></td>\n' \
261 ' <td>%s</td>\n' \
262 ' <td colspan="2">%s</td>\n' \
263 ' <td></td>\n' \
264 ' </tr>\n' \
265 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
266 self._formatEventTimestampHtml(oTestResult.tsCreated, oTestResult.tsCreated,
267 oTestResult.idTestResult, oTestSet),
268 sDisplayName,
269 'running' if oTestResult.tsElapsed is None else '', );
270 iRow += 1;
271
272 # Depth. Check if our error count is just reflecting the one of our children.
273 cErrorsBelow = 0;
274 for oChild in oTestResult.aoChildren:
275 (sChildHtml, iRow, iFailure) = self._recursivelyGenerateEvents(oChild, sName, sLineage,
276 iRow, iFailure, oTestSet, iDepth + 1);
277 sHtml += sChildHtml;
278 cErrorsBelow += oChild.cErrors;
279
280 # Messages.
281 for oMsg in oTestResult.aoMsgs:
282 sHtml += ' <tr class="%s tmtbl-events-message tmtbl-events-lvl%s">\n' \
283 ' <td>%s</td>\n' \
284 ' <td></td>\n' \
285 ' <td></td>\n' \
286 ' <td colspan="3">%s: %s</td>\n' \
287 ' <td></td>\n' \
288 ' </tr>\n' \
289 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
290 self._formatEventTimestampHtml(oMsg.tsCreated, oMsg.tsCreated, oMsg.idTestResultMsg, oTestSet),
291 webutils.escapeElem(oMsg.enmLevel),
292 webutils.escapeElem(oMsg.sMsg), );
293 iRow += 1;
294
295 # Values.
296 for oValue in oTestResult.aoValues:
297 sHtml += ' <tr class="%s tmtbl-events-value tmtbl-events-lvl%s">\n' \
298 ' <td>%s</td>\n' \
299 ' <td></td>\n' \
300 ' <td></td>\n' \
301 ' <td>%s</td>\n' \
302 ' <td class="tmtbl-events-number">%s</td>\n' \
303 ' <td class="tmtbl-events-unit">%s</td>\n' \
304 ' <td><input type="checkbox" name="%s" value="%s%s:%u" title="Include value in graph."></td>\n' \
305 ' </tr>\n' \
306 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
307 self._formatEventTimestampHtml(oValue.tsCreated, oValue.tsCreated, oValue.idTestResultValue, oTestSet),
308 webutils.escapeElem(oValue.sName),
309 utils.formatNumber(oValue.lValue).replace(' ', '&nbsp;'),
310 webutils.escapeElem(oValue.sUnit),
311 WuiMain.ksParamReportSubjectIds, ReportGraphModel.ksTypeValue, sLineage, oValue.idStrName, );
312 iRow += 1;
313
314 # Files.
315 for oFile in oTestResult.aoFiles:
316 if oFile.sMime in [ 'text/plain', ]:
317 aoLinks = [
318 WuiTmLink('%s (%s)' % (oFile.sFile, oFile.sKind), '',
319 { self._oDisp.ksParamAction: self._oDisp.ksActionViewLog,
320 self._oDisp.ksParamLogSetId: oTestSet.idTestSet,
321 self._oDisp.ksParamLogFileId: oFile.idTestResultFile, },
322 sTitle = oFile.sDescription),
323 WuiTmLink('View Raw', '',
324 { self._oDisp.ksParamAction: self._oDisp.ksActionGetFile,
325 self._oDisp.ksParamGetFileSetId: oTestSet.idTestSet,
326 self._oDisp.ksParamGetFileId: oFile.idTestResultFile,
327 self._oDisp.ksParamGetFileDownloadIt: False, },
328 sTitle = oFile.sDescription),
329 ]
330 else:
331 aoLinks = [
332 WuiTmLink('%s (%s)' % (oFile.sFile, oFile.sKind), '',
333 { self._oDisp.ksParamAction: self._oDisp.ksActionGetFile,
334 self._oDisp.ksParamGetFileSetId: oTestSet.idTestSet,
335 self._oDisp.ksParamGetFileId: oFile.idTestResultFile,
336 self._oDisp.ksParamGetFileDownloadIt: False, },
337 sTitle = oFile.sDescription),
338 ]
339 aoLinks.append(WuiTmLink('Download', '',
340 { self._oDisp.ksParamAction: self._oDisp.ksActionGetFile,
341 self._oDisp.ksParamGetFileSetId: oTestSet.idTestSet,
342 self._oDisp.ksParamGetFileId: oFile.idTestResultFile,
343 self._oDisp.ksParamGetFileDownloadIt: True, },
344 sTitle = oFile.sDescription));
345
346 sHtml += ' <tr class="%s tmtbl-events-file tmtbl-events-lvl%s">\n' \
347 ' <td>%s</td>\n' \
348 ' <td></td>\n' \
349 ' <td></td>\n' \
350 ' <td>%s</td>\n' \
351 ' <td></td>\n' \
352 ' <td></td>\n' \
353 ' <td></td>\n' \
354 ' </tr>\n' \
355 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
356 self._formatEventTimestampHtml(oFile.tsCreated, oFile.tsCreated, oFile.idTestResultFile, oTestSet),
357 '\n'.join(oLink.toHtml() for oLink in aoLinks),);
358 iRow += 1;
359
360 # Done?
361 if oTestResult.tsElapsed is not None:
362 tsEvent = oTestResult.tsCreated + oTestResult.tsElapsed;
363 sHtml += ' <tr class="%s tmtbl-events-final tmtbl-events-lvl%s tmstatusrow-%s" id="E%d">\n' \
364 ' <td>%s</td>\n' \
365 ' <td>%s</td>\n' \
366 ' <td>%s</td>\n' \
367 ' <td>%s</td>\n' \
368 ' <td colspan="2"%s>%s%s%s</td>\n' \
369 ' <td>%s</td>\n' \
370 ' </tr>\n' \
371 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth, oTestResult.enmStatus, oTestResult.idTestResult,
372 self._formatEventTimestampHtml(tsEvent, tsEvent, oTestResult.idTestResult, oTestSet),
373 sElapsedGraph,
374 webutils.escapeElem(self.formatIntervalShort(oTestResult.tsElapsed)),
375 sDisplayName,
376 ' id="failure-%u"' % (iFailure,) if oTestResult.isFailure() else '',
377 webutils.escapeElem(oTestResult.enmStatus), webutils.escapeElem(sErrCnt),
378 sChangeReason if cErrorsBelow < oTestResult.cErrors and oTestResult.oReason is None else '',
379 sResultGraph);
380 iRow += 1;
381
382 # Failure reason.
383 if oTestResult.oReason is not None:
384 sReasonText = '%s / %s' % ( oTestResult.oReason.oFailureReason.oCategory.sShort,
385 oTestResult.oReason.oFailureReason.sShort, );
386 sCommentHtml = '';
387 if oTestResult.oReason.sComment and oTestResult.oReason.sComment.strip():
388 sCommentHtml = '<br>' + webutils.escapeElem(oTestResult.oReason.sComment.strip());
389 sCommentHtml = sCommentHtml.replace('\n', '<br>');
390
391 sDetailedReason = ' <a href="?%s" class="tmtbl-show-reason">%s</a>' \
392 % ( webutils.encodeUrlParams({ self._oDisp.ksParamAction:
393 self._oDisp.ksActionTestResultFailureDetails,
394 TestResultFailureData.ksParam_idTestResult:
395 oTestResult.idTestResult,}),
396 WuiContentBase.ksShortDetailsLinkHtml,);
397
398 sHtml += ' <tr class="%s tmtbl-events-reason tmtbl-events-lvl%s">\n' \
399 ' <td>%s</td>\n' \
400 ' <td colspan="2">%s</td>\n' \
401 ' <td colspan="3">%s%s%s%s</td>\n' \
402 ' <td>%s</td>\n' \
403 ' </tr>\n' \
404 % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
405 webutils.escapeElem(self.formatTsShort(oTestResult.oReason.tsEffective)),
406 oTestResult.oReason.oAuthor.sUsername,
407 webutils.escapeElem(sReasonText), sDetailedReason, sChangeReason,
408 sCommentHtml,
409 'todo');
410 iRow += 1;
411
412 if oTestResult.isFailure():
413 iFailure += 1;
414
415 return (sHtml, iRow, iFailure);
416
417
418 def _generateMainReason(self, oTestResultTree, oTestSet):
419 """
420 Generates the form for displaying and updating the main failure reason.
421
422 oTestResultTree is an instance TestResultDataEx.
423 oTestSet is an instance of TestSetData.
424
425 """
426 _ = oTestSet;
427 sHtml = ' ';
428
429 if oTestResultTree.isFailure() or oTestResultTree.cErrors > 0:
430 sHtml += ' <h2>Failure Reason:</h2>\n';
431 oData = oTestResultTree.oReason;
432
433 # We need the failure reasons for the combobox.
434 aoFailureReasons = FailureReasonLogic(self._oDisp.getDb()).fetchForCombo('Test Sheriff, you figure out why!');
435 assert aoFailureReasons;
436
437 # For now we'll use the standard form helper.
438 sFormActionUrl = '%s?%s=%s' % ( self._oDisp.ksScriptName, self._oDisp.ksParamAction,
439 WuiMain.ksActionTestResultFailureAddPost if oData is None else
440 WuiMain.ksActionTestResultFailureEditPost )
441 fReadOnly = not self._oDisp or self._oDisp.isReadOnlyUser();
442 oForm = WuiHlpForm('failure-reason', sFormActionUrl,
443 sOnSubmit = WuiHlpForm.ksOnSubmit_AddReturnToFieldWithCurrentUrl, fReadOnly = fReadOnly);
444 oForm.addTextHidden(TestResultFailureData.ksParam_idTestResult, oTestResultTree.idTestResult);
445 oForm.addTextHidden(TestResultFailureData.ksParam_idTestSet, oTestSet.idTestSet);
446 if oData is not None:
447 oForm.addComboBox(TestResultFailureData.ksParam_idFailureReason, oData.idFailureReason, 'Reason',
448 aoFailureReasons,
449 sPostHtml = u' ' + WuiFailureReasonDetailsLink(oData.idFailureReason).toHtml()
450 + (u' ' + WuiFailureReasonAddLink('New', fBracketed = False).toHtml()
451 if not fReadOnly else u''));
452 oForm.addMultilineText(TestResultFailureData.ksParam_sComment, oData.sComment, 'Comment')
453
454 oForm.addNonText(u'%s (%s), %s'
455 % ( oData.oAuthor.sUsername, oData.oAuthor.sUsername,
456 self.formatTsShort(oData.tsEffective),),
457 'Sheriff',
458 sPostHtml = ' ' + WuiTestResultFailureDetailsLink(oData.idTestResult, "Show Details").toHtml() )
459
460 oForm.addTextHidden(TestResultFailureData.ksParam_tsEffective, oData.tsEffective);
461 oForm.addTextHidden(TestResultFailureData.ksParam_tsExpire, oData.tsExpire);
462 oForm.addTextHidden(TestResultFailureData.ksParam_uidAuthor, oData.uidAuthor);
463 oForm.addSubmit('Change Reason');
464 else:
465 oForm.addComboBox(TestResultFailureData.ksParam_idFailureReason, -1, 'Reason', aoFailureReasons,
466 sPostHtml = ' ' + WuiFailureReasonAddLink('New').toHtml() if not fReadOnly else '');
467 oForm.addMultilineText(TestResultFailureData.ksParam_sComment, '', 'Comment');
468 oForm.addTextHidden(TestResultFailureData.ksParam_tsEffective, '');
469 oForm.addTextHidden(TestResultFailureData.ksParam_tsExpire, '');
470 oForm.addTextHidden(TestResultFailureData.ksParam_uidAuthor, '');
471 oForm.addSubmit('Add Reason');
472
473 sHtml += oForm.finalize();
474 return sHtml;
475
476
477 def showTestCaseResultDetails(self, # pylint: disable=too-many-locals,too-many-statements
478 oTestResultTree,
479 oTestSet,
480 oBuildEx,
481 oValidationKitEx,
482 oTestBox,
483 oTestGroup,
484 oTestCaseEx,
485 oTestVarEx):
486 """Show detailed result"""
487 def getTcDepsHtmlList(aoTestCaseData):
488 """Get HTML <ul> list of Test Case name items"""
489 if aoTestCaseData:
490 sTmp = '<ul>'
491 for oTestCaseData in aoTestCaseData:
492 sTmp += '<li>%s</li>' % (webutils.escapeElem(oTestCaseData.sName),);
493 sTmp += '</ul>'
494 else:
495 sTmp = 'No items'
496 return sTmp
497
498 def getGrDepsHtmlList(aoGlobalResourceData):
499 """Get HTML <ul> list of Global Resource name items"""
500 if aoGlobalResourceData:
501 sTmp = '<ul>'
502 for oGlobalResourceData in aoGlobalResourceData:
503 sTmp += '<li>%s</li>' % (webutils.escapeElem(oGlobalResourceData.sName),);
504 sTmp += '</ul>'
505 else:
506 sTmp = 'No items'
507 return sTmp
508
509
510 asHtml = []
511
512 from testmanager.webui.wuireport import WuiReportSummaryLink;
513 tsReportEffectiveDate = None;
514 if oTestSet.tsDone is not None:
515 tsReportEffectiveDate = oTestSet.tsDone + datetime.timedelta(days = 4);
516 if tsReportEffectiveDate >= self.getNowTs():
517 tsReportEffectiveDate = None;
518
519 # Test result + test set details.
520 aoResultRows = [
521 WuiHtmlKeeper([ WuiTmLink(oTestCaseEx.sName, self.oWuiAdmin.ksScriptName,
522 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionTestCaseDetails,
523 TestCaseData.ksParam_idTestCase: oTestCaseEx.idTestCase,
524 self.oWuiAdmin.ksParamEffectiveDate: oTestSet.tsConfig, },
525 fBracketed = False),
526 WuiTestResultsForTestCaseLink(oTestCaseEx.idTestCase),
527 WuiReportSummaryLink(ReportModelBase.ksSubTestCase, oTestCaseEx.idTestCase,
528 tsNow = tsReportEffectiveDate, fBracketed = False),
529 ]),
530 ];
531 if oTestCaseEx.sDescription:
532 aoResultRows.append([oTestCaseEx.sDescription,]);
533 aoResultRows.append([ 'Status:', WuiRawHtml('<span class="tmspan-status-%s">%s</span>'
534 % (oTestResultTree.enmStatus, oTestResultTree.enmStatus,))]);
535 if oTestResultTree.cErrors > 0:
536 aoResultRows.append(( 'Errors:', oTestResultTree.cErrors ));
537 aoResultRows.append([ 'Elapsed:', oTestResultTree.tsElapsed ]);
538 cSecCfgTimeout = oTestCaseEx.cSecTimeout if oTestVarEx.cSecTimeout is None else oTestVarEx.cSecTimeout;
539 cSecEffTimeout = cSecCfgTimeout * oTestBox.pctScaleTimeout / 100;
540 aoResultRows.append([ 'Timeout:',
541 '%s (%s sec)' % (utils.formatIntervalSeconds(cSecEffTimeout), cSecEffTimeout,) ]);
542 if cSecEffTimeout != cSecCfgTimeout:
543 aoResultRows.append([ 'Cfg Timeout:',
544 '%s (%s sec)' % (utils.formatIntervalSeconds(cSecCfgTimeout), cSecCfgTimeout,) ]);
545 aoResultRows += [
546 ( 'Started:', WuiTmLink(self.formatTsShort(oTestSet.tsCreated), WuiMain.ksScriptName,
547 { WuiMain.ksParamAction: WuiMain.ksActionResultsUnGrouped,
548 WuiMain.ksParamEffectiveDate: oTestSet.tsCreated, },
549 fBracketed = False) ),
550 ];
551 if oTestSet.tsDone is not None:
552 aoResultRows += [ ( 'Done:',
553 WuiTmLink(self.formatTsShort(oTestSet.tsDone), WuiMain.ksScriptName,
554 { WuiMain.ksParamAction: WuiMain.ksActionResultsUnGrouped,
555 WuiMain.ksParamEffectiveDate: oTestSet.tsDone, },
556 fBracketed = False) ) ];
557 else:
558 aoResultRows += [( 'Done:', 'Still running...')];
559 aoResultRows += [( 'Config:', oTestSet.tsConfig )];
560 if oTestVarEx.cGangMembers > 1:
561 aoResultRows.append([ 'Member No:', '#%s (of %s)' % (oTestSet.iGangMemberNo, oTestVarEx.cGangMembers) ]);
562
563 aoResultRows += [
564 ( 'Test Group:',
565 WuiHtmlKeeper([ WuiTmLink(oTestGroup.sName, self.oWuiAdmin.ksScriptName,
566 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionTestGroupDetails,
567 TestGroupData.ksParam_idTestGroup: oTestGroup.idTestGroup,
568 self.oWuiAdmin.ksParamEffectiveDate: oTestSet.tsConfig, },
569 fBracketed = False),
570 WuiReportSummaryLink(ReportModelBase.ksSubTestGroup, oTestGroup.idTestGroup,
571 tsNow = tsReportEffectiveDate, fBracketed = False),
572 ]), ),
573 ];
574 if oTestVarEx.sTestBoxReqExpr is not None:
575 aoResultRows.append([ 'TestBox reqs:', oTestVarEx.sTestBoxReqExpr ]);
576 elif oTestCaseEx.sTestBoxReqExpr is not None or oTestVarEx.sTestBoxReqExpr is not None:
577 aoResultRows.append([ 'TestBox reqs:', oTestCaseEx.sTestBoxReqExpr ]);
578 if oTestVarEx.sBuildReqExpr is not None:
579 aoResultRows.append([ 'Build reqs:', oTestVarEx.sBuildReqExpr ]);
580 elif oTestCaseEx.sBuildReqExpr is not None or oTestVarEx.sBuildReqExpr is not None:
581 aoResultRows.append([ 'Build reqs:', oTestCaseEx.sBuildReqExpr ]);
582 if oTestCaseEx.sValidationKitZips is not None and oTestCaseEx.sValidationKitZips != '@VALIDATIONKIT_ZIP@':
583 aoResultRows.append([ 'Validation Kit:', oTestCaseEx.sValidationKitZips ]);
584 if oTestCaseEx.aoDepTestCases:
585 aoResultRows.append([ 'Prereq. Test Cases:', oTestCaseEx.aoDepTestCases, getTcDepsHtmlList ]);
586 if oTestCaseEx.aoDepGlobalResources:
587 aoResultRows.append([ 'Global Resources:', oTestCaseEx.aoDepGlobalResources, getGrDepsHtmlList ]);
588
589 # Builds.
590 aoBuildRows = [];
591 if oBuildEx is not None:
592 aoBuildRows += [
593 WuiHtmlKeeper([ WuiTmLink('Build', self.oWuiAdmin.ksScriptName,
594 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionBuildDetails,
595 BuildData.ksParam_idBuild: oBuildEx.idBuild,
596 self.oWuiAdmin.ksParamEffectiveDate: oTestSet.tsCreated, },
597 fBracketed = False),
598 WuiTestResultsForBuildRevLink(oBuildEx.iRevision),
599 WuiReportSummaryLink(ReportModelBase.ksSubBuild, oBuildEx.idBuild,
600 tsNow = tsReportEffectiveDate, fBracketed = False), ]),
601 ];
602 self._anchorAndAppendBinaries(oBuildEx.sBinaries, aoBuildRows);
603 aoBuildRows += [
604 ( 'Revision:', WuiSvnLinkWithTooltip(oBuildEx.iRevision, oBuildEx.oCat.sRepository,
605 fBracketed = False) ),
606 ( 'Product:', oBuildEx.oCat.sProduct ),
607 ( 'Branch:', oBuildEx.oCat.sBranch ),
608 ( 'Type:', oBuildEx.oCat.sType ),
609 ( 'Version:', oBuildEx.sVersion ),
610 ( 'Created:', oBuildEx.tsCreated ),
611 ];
612 if oBuildEx.uidAuthor is not None:
613 aoBuildRows += [ ( 'Author ID:', oBuildEx.uidAuthor ), ];
614 if oBuildEx.sLogUrl is not None:
615 aoBuildRows += [ ( 'Log:', WuiBuildLogLink(oBuildEx.sLogUrl, fBracketed = False) ), ];
616
617 aoValidationKitRows = [];
618 if oValidationKitEx is not None:
619 aoValidationKitRows += [
620 WuiTmLink('Validation Kit', self.oWuiAdmin.ksScriptName,
621 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionBuildDetails,
622 BuildData.ksParam_idBuild: oValidationKitEx.idBuild,
623 self.oWuiAdmin.ksParamEffectiveDate: oTestSet.tsCreated, },
624 fBracketed = False),
625 ];
626 self._anchorAndAppendBinaries(oValidationKitEx.sBinaries, aoValidationKitRows);
627 aoValidationKitRows += [ ( 'Revision:', WuiSvnLink(oValidationKitEx.iRevision, fBracketed = False) ) ];
628 if oValidationKitEx.oCat.sProduct != 'VBox TestSuite':
629 aoValidationKitRows += [ ( 'Product:', oValidationKitEx.oCat.sProduct ), ];
630 if oValidationKitEx.oCat.sBranch != 'trunk':
631 aoValidationKitRows += [ ( 'Product:', oValidationKitEx.oCat.sBranch ), ];
632 if oValidationKitEx.oCat.sType != 'release':
633 aoValidationKitRows += [ ( 'Type:', oValidationKitEx.oCat.sType), ];
634 if oValidationKitEx.sVersion != '0.0.0':
635 aoValidationKitRows += [ ( 'Version:', oValidationKitEx.sVersion ), ];
636 aoValidationKitRows += [
637 ( 'Created:', oValidationKitEx.tsCreated ),
638 ];
639 if oValidationKitEx.uidAuthor is not None:
640 aoValidationKitRows += [ ( 'Author ID:', oValidationKitEx.uidAuthor ), ];
641 if oValidationKitEx.sLogUrl is not None:
642 aoValidationKitRows += [ ( 'Log:', WuiBuildLogLink(oValidationKitEx.sLogUrl, fBracketed = False) ), ];
643
644 # TestBox.
645 aoTestBoxRows = [
646 WuiHtmlKeeper([ WuiTmLink(oTestBox.sName, self.oWuiAdmin.ksScriptName,
647 { self.oWuiAdmin.ksParamAction: self.oWuiAdmin.ksActionTestBoxDetails,
648 TestBoxData.ksParam_idGenTestBox: oTestSet.idGenTestBox, },
649 fBracketed = False),
650 WuiTestResultsForTestBoxLink(oTestBox.idTestBox),
651 WuiReportSummaryLink(ReportModelBase.ksSubTestBox, oTestSet.idTestBox,
652 tsNow = tsReportEffectiveDate, fBracketed = False),
653 ]),
654 ];
655 if oTestBox.sDescription:
656 aoTestBoxRows.append([oTestBox.sDescription, ]);
657 aoTestBoxRows += [
658 ( 'IP:', oTestBox.ip ),
659 #( 'UUID:', oTestBox.uuidSystem ),
660 #( 'Enabled:', oTestBox.fEnabled ),
661 #( 'Lom Kind:', oTestBox.enmLomKind ),
662 #( 'Lom IP:', oTestBox.ipLom ),
663 ( 'OS/Arch:', '%s.%s' % (oTestBox.sOs, oTestBox.sCpuArch) ),
664 ( 'OS Version:', oTestBox.sOsVersion ),
665 ( 'CPUs:', oTestBox.cCpus ),
666 ];
667 if oTestBox.sCpuName is not None:
668 aoTestBoxRows.append(['CPU Name', oTestBox.sCpuName.replace(' ', ' ')]);
669 if oTestBox.lCpuRevision is not None:
670 sMarch = oTestBox.queryCpuMicroarch();
671 if sMarch is not None:
672 aoTestBoxRows.append( ('CPU Microarch', sMarch) );
673 uFamily = oTestBox.getCpuFamily();
674 uModel = oTestBox.getCpuModel();
675 uStepping = oTestBox.getCpuStepping();
676 aoTestBoxRows += [
677 ( 'CPU Family', '%u (%#x)' % ( uFamily, uFamily, ) ),
678 ( 'CPU Model', '%u (%#x)' % ( uModel, uModel, ) ),
679 ( 'CPU Stepping', '%u (%#x)' % ( uStepping, uStepping, ) ),
680 ];
681 asFeatures = [ oTestBox.sCpuVendor, ];
682 if oTestBox.fCpuHwVirt is True: asFeatures.append(u'HW\u2011Virt');
683 if oTestBox.fCpuNestedPaging is True: asFeatures.append(u'Nested\u2011Paging');
684 if oTestBox.fCpu64BitGuest is True: asFeatures.append(u'64\u2011bit\u2011Guest');
685 if oTestBox.fChipsetIoMmu is True: asFeatures.append(u'I/O\u2011MMU');
686 aoTestBoxRows += [
687 ( 'Features:', u' '.join(asFeatures) ),
688 ( 'RAM size:', '%s MB' % (oTestBox.cMbMemory,) ),
689 ( 'Scratch Size:', '%s MB' % (oTestBox.cMbScratch,) ),
690 ( 'Scale Timeout:', '%s%%' % (oTestBox.pctScaleTimeout,) ),
691 ( 'Script Rev:', WuiSvnLink(oTestBox.iTestBoxScriptRev, fBracketed = False) ),
692 ( 'Python:', oTestBox.formatPythonVersion() ),
693 ( 'Pending Command:', oTestBox.enmPendingCmd ),
694 ];
695
696 aoRows = [
697 aoResultRows,
698 aoBuildRows,
699 aoValidationKitRows,
700 aoTestBoxRows,
701 ];
702
703 asHtml.append(self._htmlTable(aoRows));
704
705 #
706 # Convert the tree to a list of events, values, message and files.
707 #
708 sHtmlEvents = '';
709 sHtmlEvents += '<table class="tmtbl-events" id="tmtbl-events" width="100%">\n';
710 sHtmlEvents += ' <tr class="tmheader">\n' \
711 ' <th>When</th>\n' \
712 ' <th></th>\n' \
713 ' <th>Elapsed</th>\n' \
714 ' <th>Event name</th>\n' \
715 ' <th colspan="2">Value (status)</th>' \
716 ' <th></th>\n' \
717 ' </tr>\n';
718 sPrettyCmdLine = '&nbsp;\\<br>&nbsp;&nbsp;&nbsp;&nbsp;\n'.join(webutils.escapeElem(oTestCaseEx.sBaseCmd
719 + ' '
720 + oTestVarEx.sArgs).split() );
721 (sTmp, _, cFailures) = self._recursivelyGenerateEvents(oTestResultTree, sPrettyCmdLine, '', 1, 0, oTestSet, 0);
722 sHtmlEvents += sTmp;
723
724 sHtmlEvents += '</table>\n'
725
726 #
727 # Put it all together.
728 #
729 sHtml = '<table class="tmtbl-testresult-details-base" width="100%">\n';
730 sHtml += ' <tr>\n'
731 sHtml += ' <td valign="top" width="20%%">\n%s\n</td>\n' % ' <br>\n'.join(asHtml);
732
733 sHtml += ' <td valign="top" width="80%" style="padding-left:6px">\n';
734 sHtml += self._generateMainReason(oTestResultTree, oTestSet);
735
736 sHtml += ' <h2>Events:</h2>\n';
737 sHtml += ' <form action="#" method="get" id="graph-form">\n' \
738 ' <input type="hidden" name="%s" value="%s"/>\n' \
739 ' <input type="hidden" name="%s" value="%u"/>\n' \
740 ' <input type="hidden" name="%s" value="%u"/>\n' \
741 ' <input type="hidden" name="%s" value="%u"/>\n' \
742 ' <input type="hidden" name="%s" value="%u"/>\n' \
743 % ( WuiMain.ksParamAction, WuiMain.ksActionGraphWiz,
744 WuiMain.ksParamGraphWizTestBoxIds, oTestBox.idTestBox,
745 WuiMain.ksParamGraphWizBuildCatIds, oBuildEx.idBuildCategory,
746 WuiMain.ksParamGraphWizTestCaseIds, oTestSet.idTestCase,
747 WuiMain.ksParamGraphWizSrcTestSetId, oTestSet.idTestSet,
748 );
749 if oTestSet.tsDone is not None:
750 sHtml += ' <input type="hidden" name="%s" value="%s"/>\n' \
751 % ( WuiMain.ksParamEffectiveDate, oTestSet.tsDone, );
752 sHtml += ' <p>\n';
753 sFormButton = '<button type="submit" onclick="%s">Show graphs</button>' \
754 % ( webutils.escapeAttr('addDynamicGraphInputs("graph-form", "main", "%s", "%s");'
755 % (WuiMain.ksParamGraphWizWidth, WuiMain.ksParamGraphWizDpi, )) );
756 sHtml += ' ' + sFormButton + '\n';
757 sHtml += ' %s %s %s\n' \
758 % ( WuiTmLink('Log File', '',
759 { WuiMain.ksParamAction: WuiMain.ksActionViewLog,
760 WuiMain.ksParamLogSetId: oTestSet.idTestSet,
761 }),
762 WuiTmLink('Raw Log', '',
763 { WuiMain.ksParamAction: WuiMain.ksActionGetFile,
764 WuiMain.ksParamGetFileSetId: oTestSet.idTestSet,
765 WuiMain.ksParamGetFileDownloadIt: False,
766 }),
767 WuiTmLink('Download Log', '',
768 { WuiMain.ksParamAction: WuiMain.ksActionGetFile,
769 WuiMain.ksParamGetFileSetId: oTestSet.idTestSet,
770 WuiMain.ksParamGetFileDownloadIt: True,
771 }),
772 );
773 sHtml += ' </p>\n';
774 if cFailures == 1:
775 sHtml += ' <p>%s</p>\n' % ( WuiTmLink('Jump to failure', '#failure-0'), )
776 elif cFailures > 1:
777 sHtml += ' <p>Jump to failure: ';
778 if cFailures <= 13:
779 for iFailure in range(0, cFailures):
780 sHtml += ' ' + WuiTmLink('#%u' % (iFailure,), '#failure-%u' % (iFailure,)).toHtml();
781 else:
782 for iFailure in range(0, 6):
783 sHtml += ' ' + WuiTmLink('#%u' % (iFailure,), '#failure-%u' % (iFailure,)).toHtml();
784 sHtml += ' ... ';
785 for iFailure in range(cFailures - 6, cFailures):
786 sHtml += ' ' + WuiTmLink('#%u' % (iFailure,), '#failure-%u' % (iFailure,)).toHtml();
787 sHtml += ' </p>\n';
788
789 sHtml += sHtmlEvents;
790 sHtml += ' <p>' + sFormButton + '</p>\n';
791 sHtml += ' </form>\n';
792 sHtml += ' </td>\n';
793
794 sHtml += ' </tr>\n';
795 sHtml += '</table>\n';
796
797 return ('Test Case result details', sHtml)
798
799
800class WuiGroupedResultList(WuiListContentBase):
801 """
802 WUI results content generator.
803 """
804
805 def __init__(self, aoEntries, cEntriesCount, iPage, cItemsPerPage, tsEffective, fnDPrint, oDisp,
806 aiSelectedSortColumns = None):
807 """Override initialization"""
808 WuiListContentBase.__init__(self, aoEntries, iPage, cItemsPerPage, tsEffective,
809 sTitle = 'Ungrouped (%d)' % cEntriesCount, sId = 'results',
810 fnDPrint = fnDPrint, oDisp = oDisp, aiSelectedSortColumns = aiSelectedSortColumns);
811
812 self._cEntriesCount = cEntriesCount
813
814 self._asColumnHeaders = [
815 'Start',
816 'Product Build',
817 'Kit',
818 'Box',
819 'OS.Arch',
820 'Test Case',
821 'Elapsed',
822 'Result',
823 'Reason',
824 ];
825 self._asColumnAttribs = ['align="center"', 'align="center"', 'align="center"',
826 'align="center"', 'align="center"', 'align="center"',
827 'align="center"', 'align="center"', 'align="center"',
828 'align="center"', 'align="center"', 'align="center"',
829 'align="center"', ];
830
831
832 # Prepare parameter lists.
833 self._dTestBoxLinkParams = self._oDisp.getParameters();
834 self._dTestBoxLinkParams[WuiMain.ksParamAction] = WuiMain.ksActionResultsGroupedByTestBox;
835
836 self._dTestCaseLinkParams = self._oDisp.getParameters();
837 self._dTestCaseLinkParams[WuiMain.ksParamAction] = WuiMain.ksActionResultsGroupedByTestCase;
838
839 self._dRevLinkParams = self._oDisp.getParameters();
840 self._dRevLinkParams[WuiMain.ksParamAction] = WuiMain.ksActionResultsGroupedByBuildRev;
841
842
843
844 def _formatListEntry(self, iEntry):
845 """
846 Format *show all* table entry
847 """
848 oEntry = self._aoEntries[iEntry];
849
850 from testmanager.webui.wuiadmin import WuiAdmin;
851 from testmanager.webui.wuireport import WuiReportSummaryLink;
852
853 oValidationKit = None;
854 if oEntry.idBuildTestSuite is not None:
855 oValidationKit = WuiTmLink('r%s' % (oEntry.iRevisionTestSuite,),
856 WuiAdmin.ksScriptName,
857 { WuiAdmin.ksParamAction: WuiAdmin.ksActionBuildDetails,
858 BuildData.ksParam_idBuild: oEntry.idBuildTestSuite },
859 fBracketed = False);
860
861 aoTestSetLinks = [];
862 aoTestSetLinks.append(WuiTmLink(oEntry.enmStatus,
863 WuiMain.ksScriptName,
864 { WuiMain.ksParamAction: WuiMain.ksActionTestResultDetails,
865 TestSetData.ksParam_idTestSet: oEntry.idTestSet },
866 fBracketed = False));
867 if oEntry.cErrors > 0:
868 aoTestSetLinks.append(WuiRawHtml('-'));
869 aoTestSetLinks.append(WuiTmLink('%d error%s' % (oEntry.cErrors, '' if oEntry.cErrors == 1 else 's', ),
870 WuiMain.ksScriptName,
871 { WuiMain.ksParamAction: WuiMain.ksActionTestResultDetails,
872 TestSetData.ksParam_idTestSet: oEntry.idTestSet },
873 sFragmentId = 'failure-0', fBracketed = False));
874
875
876 self._dTestBoxLinkParams[WuiMain.ksParamGroupMemberId] = oEntry.idTestBox;
877 self._dTestCaseLinkParams[WuiMain.ksParamGroupMemberId] = oEntry.idTestCase;
878 self._dRevLinkParams[WuiMain.ksParamGroupMemberId] = oEntry.iRevision;
879
880 sTestBoxTitle = u'';
881 if oEntry.sCpuVendor is not None:
882 sTestBoxTitle += 'CPU vendor:\t%s\n' % ( oEntry.sCpuVendor, );
883 if oEntry.sCpuName is not None:
884 sTestBoxTitle += 'CPU name:\t%s\n' % ( ' '.join(oEntry.sCpuName.split()), );
885 if oEntry.sOsVersion is not None:
886 sTestBoxTitle += 'OS version:\t%s\n' % ( oEntry.sOsVersion, );
887 asFeatures = [];
888 if oEntry.fCpuHwVirt is True:
889 if oEntry.sCpuVendor is None:
890 asFeatures.append(u'HW\u2011Virt');
891 elif oEntry.sCpuVendor in ['AuthenticAMD',]:
892 asFeatures.append(u'HW\u2011Virt(AMD\u2011V)');
893 else:
894 asFeatures.append(u'HW\u2011Virt(VT\u2011x)');
895 if oEntry.fCpuNestedPaging is True: asFeatures.append(u'Nested\u2011Paging');
896 if oEntry.fCpu64BitGuest is True: asFeatures.append(u'64\u2011bit\u2011Guest');
897 #if oEntry.fChipsetIoMmu is True: asFeatures.append(u'I/O\u2011MMU');
898 sTestBoxTitle += u'CPU features:\t' + u', '.join(asFeatures);
899
900 # Testcase
901 if oEntry.sSubName:
902 sTestCaseName = '%s / %s' % (oEntry.sTestCaseName, oEntry.sSubName,);
903 else:
904 sTestCaseName = oEntry.sTestCaseName;
905
906 # Reason:
907 aoReasons = [];
908 for oIt in oEntry.aoFailureReasons:
909 sReasonTitle = 'Reason: \t%s\n' % ( oIt.oFailureReason.sShort, );
910 sReasonTitle += 'Category:\t%s\n' % ( oIt.oFailureReason.oCategory.sShort, );
911 sReasonTitle += 'Assigned:\t%s\n' % ( self.formatTsShort(oIt.tsFailureReasonAssigned), );
912 sReasonTitle += 'By User: \t%s\n' % ( oIt.oFailureReasonAssigner.sUsername, );
913 if oIt.sFailureReasonComment:
914 sReasonTitle += 'Comment: \t%s\n' % ( oIt.sFailureReasonComment, );
915 if oIt.oFailureReason.iTicket is not None and oIt.oFailureReason.iTicket > 0:
916 sReasonTitle += 'xTracker:\t#%s\n' % ( oIt.oFailureReason.iTicket, );
917 for i, sUrl in enumerate(oIt.oFailureReason.asUrls):
918 sUrl = sUrl.strip();
919 if sUrl:
920 sReasonTitle += 'URL#%u: \t%s\n' % ( i, sUrl, );
921 aoReasons.append(WuiTmLink(oIt.oFailureReason.sShort, WuiAdmin.ksScriptName,
922 { WuiAdmin.ksParamAction: WuiAdmin.ksActionFailureReasonDetails,
923 FailureReasonData.ksParam_idFailureReason: oIt.oFailureReason.idFailureReason },
924 sTitle = sReasonTitle));
925
926 return [
927 oEntry.tsCreated,
928 [ WuiTmLink('%s %s (%s)' % (oEntry.sProduct, oEntry.sVersion, oEntry.sType,),
929 WuiMain.ksScriptName, self._dRevLinkParams, sTitle = '%s' % (oEntry.sBranch,), fBracketed = False),
930 WuiSvnLinkWithTooltip(oEntry.iRevision, 'vbox'), ## @todo add sRepository TestResultListingData
931 WuiTmLink(self.ksShortDetailsLink, WuiAdmin.ksScriptName,
932 { WuiAdmin.ksParamAction: WuiAdmin.ksActionBuildDetails,
933 BuildData.ksParam_idBuild: oEntry.idBuild },
934 fBracketed = False),
935 ],
936 oValidationKit,
937 [ WuiTmLink(oEntry.sTestBoxName, WuiMain.ksScriptName, self._dTestBoxLinkParams, fBracketed = False,
938 sTitle = sTestBoxTitle),
939 WuiTmLink(self.ksShortDetailsLink, WuiAdmin.ksScriptName,
940 { WuiAdmin.ksParamAction: WuiAdmin.ksActionTestBoxDetails,
941 TestBoxData.ksParam_idTestBox: oEntry.idTestBox },
942 fBracketed = False),
943 WuiReportSummaryLink(ReportModelBase.ksSubTestBox, oEntry.idTestBox, fBracketed = False), ],
944 '%s.%s' % (oEntry.sOs, oEntry.sArch),
945 [ WuiTmLink(sTestCaseName, WuiMain.ksScriptName, self._dTestCaseLinkParams, fBracketed = False,
946 sTitle = (oEntry.sBaseCmd + ' ' + oEntry.sArgs) if oEntry.sArgs else oEntry.sBaseCmd),
947 WuiTmLink(self.ksShortDetailsLink, WuiAdmin.ksScriptName,
948 { WuiAdmin.ksParamAction: WuiAdmin.ksActionTestCaseDetails,
949 TestCaseData.ksParam_idTestCase: oEntry.idTestCase },
950 fBracketed = False),
951 WuiReportSummaryLink(ReportModelBase.ksSubTestCase, oEntry.idTestCase, fBracketed = False), ],
952 oEntry.tsElapsed,
953 aoTestSetLinks,
954 aoReasons
955 ];
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