VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py@ 54711

Last change on this file since 54711 was 52776, checked in by vboxsync, 10 years ago

fix OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.3 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuimain.py 52776 2014-09-17 14:51:43Z vboxsync $
3
4"""
5Test Manager Core - WUI - The Main page.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2014 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: 52776 $"
30
31# Standard Python imports.
32
33# Validation Kit imports.
34from testmanager import config;
35from testmanager.webui.wuibase import WuiDispatcherBase, WuiException;
36from testmanager.webui.wuicontentbase import WuiTmLink;
37from testmanager.core.report import ReportLazyModel, ReportGraphModel, ReportModelBase;
38from testmanager.core.testresults import TestResultLogic, TestResultFileDataEx;
39from testmanager.core.base import TMExceptionBase, TMTooManyRows;
40from testmanager.core.testset import TestSetData, TestSetLogic;
41from testmanager.core.build import BuildDataEx;
42from testmanager.core.testbox import TestBoxData
43from testmanager.core.testgroup import TestGroupData;
44from testmanager.core.testcase import TestCaseDataEx
45from testmanager.core.testcaseargs import TestCaseArgsDataEx
46from testmanager.core.vcsrevisions import VcsRevisionLogic;
47from common import webutils, utils;
48
49
50class WuiMain(WuiDispatcherBase):
51 """
52 WUI Main page.
53
54 Note! All cylic dependency avoiance stuff goes here in the dispatcher code,
55 not in the action specific code. This keeps the uglyness in one place
56 and reduces load time dependencies in the more critical code path.
57 """
58
59 ## The name of the script.
60 ksScriptName = 'index.py'
61
62 ## @name Actions
63 ## @{
64 ksActionResultsUnGrouped = 'ResultsUnGrouped'
65 ksActionResultsGroupedBySchedGroup = 'ResultsGroupedBySchedGroup'
66 ksActionResultsGroupedByTestGroup = 'ResultsGroupedByTestGroup'
67 ksActionResultsGroupedByBuildRev = 'ResultsGroupedByBuildRev'
68 ksActionResultsGroupedByTestBox = 'ResultsGroupedByTestBox'
69 ksActionResultsGroupedByTestCase = 'ResultsGroupedByTestCase'
70 ksActionTestResultDetails = 'TestResultDetails'
71 ksActionViewLog = 'ViewLog'
72 ksActionGetFile = 'GetFile'
73 ksActionReportSummary = 'ReportSummary';
74 ksActionReportRate = 'ReportRate';
75 ksActionReportFailureReasons = 'ReportFailureReasons';
76 ksActionGraphWiz = 'GraphWiz';
77 ksActionVcsHistoryTooltip = 'VcsHistoryTooltip';
78 ## @}
79
80 ## @name Standard report parameters
81 ## @{
82 ksParamReportPeriods = 'cPeriods';
83 ksParamReportPeriodInHours = 'cHoursPerPeriod';
84 ksParamReportSubject = 'sSubject';
85 ksParamReportSubjectIds = 'SubjectIds';
86 ## @}
87
88 ## @name Graph Wizard parameters
89 ## Common parameters: ksParamReportPeriods, ksParamReportPeriodInHours, ksParamReportSubjectIds,
90 ## ksParamReportSubject, ksParamEffectivePeriod, and ksParamEffectiveDate.
91 ## @{
92 ksParamGraphWizTestBoxIds = 'aidTestBoxes';
93 ksParamGraphWizBuildCatIds = 'aidBuildCats';
94 ksParamGraphWizTestCaseIds = 'aidTestCases';
95 ksParamGraphWizSepTestVars = 'fSepTestVars';
96 ksParamGraphWizImpl = 'enmImpl';
97 ksParamGraphWizWidth = 'cx';
98 ksParamGraphWizHeight = 'cy';
99 ksParamGraphWizDpi = 'dpi';
100 ksParamGraphWizFontSize = 'cPtFont';
101 ksParamGraphWizErrorBarY = 'fErrorBarY';
102 ksParamGraphWizMaxErrorBarY = 'cMaxErrorBarY';
103 ksParamGraphWizMaxPerGraph = 'cMaxPerGraph';
104 ksParamGraphWizXkcdStyle = 'fXkcdStyle';
105 ksParamGraphWizTabular = 'fTabular';
106 ksParamGraphWizSrcTestSetId = 'idSrcTestSet';
107 ## @}
108
109 ## @name Graph implementations values for ksParamGraphWizImpl.
110 ## @{
111 ksGraphWizImpl_Default = 'default';
112 ksGraphWizImpl_Matplotlib = 'matplotlib';
113 ksGraphWizImpl_Charts = 'charts';
114 kasGraphWizImplValid = [ ksGraphWizImpl_Default, ksGraphWizImpl_Matplotlib, ksGraphWizImpl_Charts];
115 kaasGraphWizImplCombo = [
116 ( ksGraphWizImpl_Default, 'Default' ),
117 ( ksGraphWizImpl_Matplotlib, 'Matplotlib (server)' ),
118 ( ksGraphWizImpl_Charts, 'Google Charts (client)'),
119 ];
120 ## @}
121
122 ## @name Log Viewer parameters.
123 ## @{
124 ksParamLogSetId = 'LogViewer_idTestSet';
125 ksParamLogFileId = 'LogViewer_idFile';
126 ksParamLogChunkSize = 'LogViewer_cbChunk';
127 ksParamLogChunkNo = 'LogViewer_iChunk';
128 ## @}
129
130 ## @name File getter parameters.
131 ## @{
132 ksParamGetFileSetId = 'GetFile_idTestSet';
133 ksParamGetFileId = 'GetFile_idFile';
134 ksParamGetFileDownloadIt = 'GetFile_fDownloadIt';
135 ## @}
136
137 ## @name VCS history parameters.
138 ## @{
139 ksParamVcsHistoryRepository = 'repo';
140 ksParamVcsHistoryRevision = 'rev';
141 ksParamVcsHistoryEntries = 'cEntries';
142 ## @}
143
144 ## Effective time period. one of the first column values in kaoResultPeriods.
145 ksParamEffectivePeriod = 'sEffectivePeriod'
146
147 ## If this param is specified, then show only results for this member when results grouped by some parameter.
148 ksParamGroupMemberId = 'GroupMemberId'
149
150 ## Optional parameter for indicating whether to restrict the listing to failures only.
151 ksParamOnlyFailures = 'OnlyFailures'
152
153 ## Test result period values.
154 kaoResultPeriods = [
155 ( '1 hour', 'One hour', 1 ),
156 ( '2 hours', 'Two hours', 2 ),
157 ( '3 hours', 'Three hours', 3 ),
158 ( '6 hours', 'Six hours', 6 ),
159 ( '12 hours', '12 hours', 12 ),
160
161 ( '1 day', 'One day', 24 ),
162 ( '2 days', 'Two days', 48 ),
163 ( '3 days', 'Three days', 72 ),
164
165 ( '1 week', 'One week', 168 ),
166 ( '2 weeks', 'Two weeks', 336 ),
167 ( '3 weeks', 'Three weeks', 504 ),
168
169 ( '1 month', 'One month', 31 * 24 ), # The approx hour count varies with the start date.
170 ( '2 months', 'Two month', (31 + 31) * 24 ), # Using maximum values.
171 ( '3 months', 'Three month', (31 + 30 + 31) * 24 ),
172
173 ( '6 months', 'Six month', (31 + 31 + 30 + 31 + 30 + 31) * 24 ),
174
175 ( '1 year', 'One year', 365 * 24 ),
176 ];
177 ## The default test result period.
178 ksResultPeriodDefault = '3 hours';
179
180
181
182 def __init__(self, oSrvGlue):
183 WuiDispatcherBase.__init__(self, oSrvGlue, self.ksScriptName);
184
185 self._sTemplate = 'template.html'
186
187 #
188 # Populate the action dispatcher dictionary.
189 #
190
191 # Use short form to avoid hitting the right margin (130) when using lambda.
192 d = self._dDispatch; # pylint: disable=C0103
193
194 from testmanager.webui.wuitestresult import WuiGroupedResultList;
195 #d[self.ksActionResultsUnGrouped] = lambda: self._actionResultsListing(TestResultLogic, WuiGroupedResultList)
196 d[self.ksActionResultsUnGrouped] = lambda: self._actionGroupedResultsListing(
197 TestResultLogic.ksResultsGroupingTypeNone,
198 TestResultLogic,
199 WuiGroupedResultList)
200
201 d[self.ksActionResultsGroupedByTestGroup] = lambda: self._actionGroupedResultsListing(
202 TestResultLogic.ksResultsGroupingTypeTestGroup,
203 TestResultLogic,
204 WuiGroupedResultList)
205
206 d[self.ksActionResultsGroupedByBuildRev] = lambda: self._actionGroupedResultsListing(
207 TestResultLogic.ksResultsGroupingTypeBuildRev,
208 TestResultLogic,
209 WuiGroupedResultList)
210
211 d[self.ksActionResultsGroupedByTestBox] = lambda: self._actionGroupedResultsListing(
212 TestResultLogic.ksResultsGroupingTypeTestBox,
213 TestResultLogic,
214 WuiGroupedResultList)
215
216 d[self.ksActionResultsGroupedByTestCase] = lambda: self._actionGroupedResultsListing(
217 TestResultLogic.ksResultsGroupingTypeTestCase,
218 TestResultLogic,
219 WuiGroupedResultList)
220
221 d[self.ksActionResultsGroupedBySchedGroup] = lambda: self._actionGroupedResultsListing(
222 TestResultLogic.ksResultsGroupingTypeSchedGroup,
223 TestResultLogic,
224 WuiGroupedResultList)
225
226 d[self.ksActionTestResultDetails] = self.actionTestResultDetails
227
228 d[self.ksActionViewLog] = self.actionViewLog;
229 d[self.ksActionGetFile] = self.actionGetFile;
230 from testmanager.webui.wuireport import WuiReportSummary, WuiReportSuccessRate, WuiReportFailureReasons;
231 d[self.ksActionReportSummary] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportSummary);
232 d[self.ksActionReportRate] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportSuccessRate);
233 d[self.ksActionReportFailureReasons] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportFailureReasons);
234 d[self.ksActionGraphWiz] = self._actionGraphWiz;
235 d[self.ksActionVcsHistoryTooltip] = self._actionVcsHistoryTooltip;
236
237
238 #
239 # Popupate the menus.
240 #
241
242 # Additional URL parameters keeping for time navigation.
243 sExtraTimeNav = ''
244 dCurParams = oSrvGlue.getParameters()
245 if dCurParams is not None:
246 asActionUrlExtras = [ self.ksParamItemsPerPage, self.ksParamEffectiveDate, self.ksParamEffectivePeriod, ];
247 for sExtraParam in asActionUrlExtras:
248 if sExtraParam in dCurParams:
249 sExtraTimeNav += '&%s' % webutils.encodeUrlParams({sExtraParam: dCurParams[sExtraParam]})
250
251 # Shorthand to keep within margins.
252 sActUrlBase = self._sActionUrlBase;
253
254 self._aaoMenus = \
255 [
256 [
257 'Inbox', sActUrlBase + 'TODO', ## @todo list of failures that needs categorizing.
258 []
259 ],
260 [
261 'Reports', sActUrlBase + self.ksActionReportSummary,
262 [
263 [ 'Summary', sActUrlBase + self.ksActionReportSummary ],
264 [ 'Success Rate', sActUrlBase + self.ksActionReportRate ],
265 [ 'Failure Reasons', sActUrlBase + self.ksActionReportFailureReasons ],
266 ]
267 ],
268 [
269 'Test Results', sActUrlBase + self.ksActionResultsUnGrouped + sExtraTimeNav,
270 [
271 [ 'Ungrouped results', sActUrlBase + self.ksActionResultsUnGrouped + sExtraTimeNav ],
272 [ 'Grouped by Scheduling Group', sActUrlBase + self.ksActionResultsGroupedBySchedGroup + sExtraTimeNav ],
273 [ 'Grouped by Test Group', sActUrlBase + self.ksActionResultsGroupedByTestGroup + sExtraTimeNav ],
274 [ 'Grouped by TestBox', sActUrlBase + self.ksActionResultsGroupedByTestBox + sExtraTimeNav ],
275 [ 'Grouped by Test Case', sActUrlBase + self.ksActionResultsGroupedByTestCase + sExtraTimeNav ],
276 [ 'Grouped by Revision', sActUrlBase + self.ksActionResultsGroupedByBuildRev + sExtraTimeNav ],
277 ]
278 ],
279 [
280 '> Admin', 'admin.py?' + webutils.encodeUrlParams(self._dDbgParams), []
281 ],
282 ];
283
284
285 def _actionDefault(self):
286 """Show the default admin page."""
287 from testmanager.webui.wuitestresult import WuiGroupedResultList;
288 self._sAction = self.ksActionResultsUnGrouped
289 return self._actionGroupedResultsListing(TestResultLogic.ksResultsGroupingTypeNone,
290 TestResultLogic,
291 WuiGroupedResultList)
292
293
294 #
295 # Navigation bar stuff
296 #
297
298 def _generateStatusSelector(self, dParams, fOnlyFailures):
299 """
300 Generate HTML code for the status code selector. Currently very simple.
301 """
302 dParams[self.ksParamOnlyFailures] = not fOnlyFailures;
303 return WuiTmLink('Show all results' if fOnlyFailures else 'Only show failed tests', '', dParams,
304 fBracketed = False).toHtml();
305
306 def _generateTimeSelector(self, dParams, sPreamble, sPostamble):
307 """
308 Generate HTML code for time selector.
309 """
310
311 if WuiDispatcherBase.ksParamEffectiveDate in dParams:
312 tsEffective = dParams[WuiDispatcherBase.ksParamEffectiveDate]
313 del dParams[WuiDispatcherBase.ksParamEffectiveDate]
314 else:
315 tsEffective = ''
316
317 # Forget about page No when changing a period
318 if WuiDispatcherBase.ksParamPageNo in dParams:
319 del dParams[WuiDispatcherBase.ksParamPageNo]
320
321
322 sHtmlTimeSelector = '<form name="TimeForm" method="GET">\n'
323 sHtmlTimeSelector += sPreamble;
324 sHtmlTimeSelector += '\n <select name="%s" onchange="window.location=' % WuiDispatcherBase.ksParamEffectiveDate
325 sHtmlTimeSelector += '\'?%s&%s=\' + ' % (webutils.encodeUrlParams(dParams), WuiDispatcherBase.ksParamEffectiveDate)
326 sHtmlTimeSelector += 'this.options[this.selectedIndex].value;" title="Effective date">\n'
327
328 aoWayBackPoints = [
329 ('+0000-00-00 00:00:00.00', 'Now', ' title="Present Day. Present Time."'), # lain :)
330
331 ('-0000-00-00 01:00:00.00', 'One hour ago', ''),
332 ('-0000-00-00 02:00:00.00', 'Two hours ago', ''),
333 ('-0000-00-00 03:00:00.00', 'Three hours ago', ''),
334
335 ('-0000-00-01 00:00:00.00', 'One day ago', ''),
336 ('-0000-00-02 00:00:00.00', 'Two days ago', ''),
337 ('-0000-00-03 00:00:00.00', 'Three days ago', ''),
338
339 ('-0000-00-07 00:00:00.00', 'One week ago', ''),
340 ('-0000-00-14 00:00:00.00', 'Two weeks ago', ''),
341 ('-0000-00-21 00:00:00.00', 'Three weeks ago', ''),
342
343 ('-0000-01-00 00:00:00.00', 'One month ago', ''),
344 ('-0000-02-00 00:00:00.00', 'Two months ago', ''),
345 ('-0000-03-00 00:00:00.00', 'Three months ago', ''),
346 ('-0000-04-00 00:00:00.00', 'Four months ago', ''),
347 ('-0000-05-00 00:00:00.00', 'Five months ago', ''),
348 ('-0000-06-00 00:00:00.00', 'Half a year ago', ''),
349
350 ('-0001-00-00 00:00:00.00', 'One year ago', ''),
351 ]
352 fSelected = False;
353 for sTimestamp, sWayBackPointCaption, sExtraAttrs in aoWayBackPoints:
354 if sTimestamp == tsEffective:
355 fSelected = True;
356 sHtmlTimeSelector += ' <option value="%s"%s%s>%s</option>\n' \
357 % (webutils.quoteUrl(sTimestamp),
358 ' selected="selected"' if sTimestamp == tsEffective else '',
359 sExtraAttrs, sWayBackPointCaption)
360 if not fSelected and tsEffective != '':
361 sHtmlTimeSelector += ' <option value="%s" selected>%s</option>\n' \
362 % (webutils.quoteUrl(tsEffective), tsEffective)
363
364 sHtmlTimeSelector += ' </select>\n';
365 sHtmlTimeSelector += sPostamble;
366 sHtmlTimeSelector += '\n</form>\n'
367
368 return sHtmlTimeSelector
369
370 def _generateTimeWalker(self, dParams, tsEffective, sCurPeriod):
371 """
372 Generates HTML code for walking back and forth in time.
373 """
374 # Have to do some math here. :-/
375 if tsEffective is None:
376 self._oDb.execute('SELECT CURRENT_TIMESTAMP - \'' + sCurPeriod + '\'::interval');
377 tsNext = None;
378 tsPrev = self._oDb.fetchOne()[0];
379 else:
380 self._oDb.execute('SELECT %s::TIMESTAMP - \'' + sCurPeriod + '\'::interval,\n'
381 ' %s::TIMESTAMP + \'' + sCurPeriod + '\'::interval',
382 (tsEffective, tsEffective,));
383 tsPrev, tsNext = self._oDb.fetchOne();
384
385 # Forget about page No when changing a period
386 if WuiDispatcherBase.ksParamPageNo in dParams:
387 del dParams[WuiDispatcherBase.ksParamPageNo]
388
389 # Format.
390 dParams[WuiDispatcherBase.ksParamEffectiveDate] = str(tsPrev);
391 sPrev = '<a href="?%s" title="One period earlier">&lt;&lt;</a>&nbsp;&nbsp;' \
392 % (webutils.encodeUrlParams(dParams),);
393
394 if tsNext is not None:
395 dParams[WuiDispatcherBase.ksParamEffectiveDate] = str(tsNext);
396 sNext = '&nbsp;&nbsp;<a href="?%s" title="One period later">&gt;&gt;</a>' \
397 % (webutils.encodeUrlParams(dParams),);
398 else:
399 sNext = '&nbsp;&nbsp;&gt;&gt;';
400
401 return self._generateTimeSelector(self.getParameters(), sPrev, sNext);
402
403 def _generateResultPeriodSelector(self, dParams, sCurPeriod):
404 """
405 Generate HTML code for result period selector.
406 """
407
408 if self.ksParamEffectivePeriod in dParams:
409 del dParams[self.ksParamEffectivePeriod];
410
411 # Forget about page No when changing a period
412 if WuiDispatcherBase.ksParamPageNo in dParams:
413 del dParams[WuiDispatcherBase.ksParamPageNo]
414
415 sHtmlPeriodSelector = '<form name="PeriodForm" method="GET">\n'
416 sHtmlPeriodSelector += ' Period is\n'
417 sHtmlPeriodSelector += ' <select name="%s" onchange="window.location=' % self.ksParamEffectivePeriod
418 sHtmlPeriodSelector += '\'?%s&%s=\' + ' % (webutils.encodeUrlParams(dParams), self.ksParamEffectivePeriod)
419 sHtmlPeriodSelector += 'this.options[this.selectedIndex].value;">\n'
420
421 for sPeriodValue, sPeriodCaption, _ in self.kaoResultPeriods:
422 sHtmlPeriodSelector += ' <option value="%s"%s>%s</option>\n' \
423 % (webutils.quoteUrl(sPeriodValue),
424 ' selected="selected"' if sPeriodValue == sCurPeriod else '',
425 sPeriodCaption)
426
427 sHtmlPeriodSelector += ' </select>\n' \
428 '</form>\n'
429
430 return sHtmlPeriodSelector
431
432 def _generateGroupContentSelector(self, aoGroupMembers, iCurrentMember, sAltAction):
433 """
434 Generate HTML code for group content selector.
435 """
436
437 dParams = self.getParameters()
438
439 if self.ksParamGroupMemberId in dParams:
440 del dParams[self.ksParamGroupMemberId]
441
442 if sAltAction is not None:
443 if self.ksParamAction in dParams:
444 del dParams[self.ksParamAction];
445 dParams[self.ksParamAction] = sAltAction;
446
447 sHtmlSelector = '<form name="GroupContentForm" method="GET">\n'
448 sHtmlSelector += ' <select name="%s" onchange="window.location=' % self.ksParamGroupMemberId
449 sHtmlSelector += '\'?%s&%s=\' + ' % (webutils.encodeUrlParams(dParams), self.ksParamGroupMemberId)
450 sHtmlSelector += 'this.options[this.selectedIndex].value;">\n'
451
452 sHtmlSelector += '<option value="-1">All</option>\n'
453
454 for iGroupMemberId, sGroupMemberName in aoGroupMembers:
455 if iGroupMemberId is not None:
456 sHtmlSelector += ' <option value="%s"%s>%s</option>\n' \
457 % (iGroupMemberId,
458 ' selected="selected"' if iGroupMemberId == iCurrentMember else '',
459 sGroupMemberName)
460
461 sHtmlSelector += ' </select>\n' \
462 '</form>\n'
463
464 return sHtmlSelector
465
466 def _generatePagesSelector(self, dParams, cItems, cItemsPerPage, iPage):
467 """
468 Generate HTML code for pages (1, 2, 3 ... N) selector
469 """
470
471 if WuiDispatcherBase.ksParamPageNo in dParams:
472 del dParams[WuiDispatcherBase.ksParamPageNo]
473
474 sHrefPtr = '<a href="?%s&%s=' % (webutils.encodeUrlParams(dParams).replace('%', '%%'),
475 WuiDispatcherBase.ksParamPageNo)
476 sHrefPtr += '%d">%s</a>'
477
478 cNumOfPages = (cItems + cItemsPerPage - 1) / cItemsPerPage;
479 cPagesToDisplay = 10
480 cPagesRangeStart = iPage - cPagesToDisplay / 2 \
481 if not iPage - cPagesToDisplay / 2 < 0 else 0
482 cPagesRangeEnd = cPagesRangeStart + cPagesToDisplay \
483 if not cPagesRangeStart + cPagesToDisplay > cNumOfPages else cNumOfPages
484 # Adjust pages range
485 if cNumOfPages < cPagesToDisplay:
486 cPagesRangeStart = 0
487 cPagesRangeEnd = cNumOfPages
488
489 # 1 2 3 4...
490 sHtmlPager = '&nbsp;\n'.join(sHrefPtr % (x, str(x + 1)) if x != iPage else str(x + 1)
491 for x in range(cPagesRangeStart, cPagesRangeEnd))
492 if cPagesRangeStart > 0:
493 sHtmlPager = '%s&nbsp; ... &nbsp;\n' % (sHrefPtr % (0, str(1))) + sHtmlPager
494 if cPagesRangeEnd < cNumOfPages:
495 sHtmlPager += ' ... %s\n' % (sHrefPtr % (cNumOfPages, str(cNumOfPages + 1)))
496
497 # Prev/Next (using << >> because &laquo; and &raquo are too tiny).
498 if iPage > 0:
499 dParams[WuiDispatcherBase.ksParamPageNo] = iPage - 1
500 sHtmlPager = ('<a title="Previous page" href="?%s">&lt;&lt;</a>&nbsp;&nbsp;\n'
501 % (webutils.encodeUrlParams(dParams), )) \
502 + sHtmlPager;
503 else:
504 sHtmlPager = '&lt;&lt;&nbsp;&nbsp;\n' + sHtmlPager
505
506 if iPage + 1 < cNumOfPages:
507 dParams[WuiDispatcherBase.ksParamPageNo] = iPage + 1
508 sHtmlPager += '\n&nbsp; <a title="Next page" href="?%s">&gt;&gt;</a>\n' % (webutils.encodeUrlParams(dParams),)
509 else:
510 sHtmlPager += '\n&nbsp; &gt;&gt;\n'
511
512 return sHtmlPager
513
514 def _generateItemPerPageSelector(self, dParams, cItemsPerPage):
515 """
516 Generate HTML code for items per page selector
517 """
518
519 if WuiDispatcherBase.ksParamItemsPerPage in dParams:
520 del dParams[WuiDispatcherBase.ksParamItemsPerPage]
521
522 # Forced reset of the page number
523 dParams[WuiDispatcherBase.ksParamPageNo] = 0
524 sHtmlItemsPerPageSelector = '<form name="AgesPerPageForm" method="GET">\n' \
525 ' Max <select name="%s" onchange="window.location=\'?%s&%s=\' + ' \
526 'this.options[this.selectedIndex].value;" title="Max items per page">\n' \
527 % (WuiDispatcherBase.ksParamItemsPerPage,
528 webutils.encodeUrlParams(dParams),
529 WuiDispatcherBase.ksParamItemsPerPage)
530
531 aiItemsPerPage = [16, 32, 64, 128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096];
532 for iItemsPerPage in aiItemsPerPage:
533 sHtmlItemsPerPageSelector += ' <option value="%d" %s>%d</option>\n' \
534 % (iItemsPerPage,
535 'selected="selected"' if iItemsPerPage == cItemsPerPage else '',
536 iItemsPerPage)
537 sHtmlItemsPerPageSelector += ' </select> items per page\n' \
538 '</form>\n'
539
540 return sHtmlItemsPerPageSelector
541
542 def _generateResultNavigation(self, cItems, cItemsPerPage, iPage, tsEffective, sCurPeriod, fOnlyFailures,
543 sHtmlMemberSelector):
544 """ Make custom time navigation bar for the results. """
545
546 # Generate the elements.
547 sHtmlStatusSelector = self._generateStatusSelector(self.getParameters(), fOnlyFailures);
548 sHtmlPeriodSelector = self._generateResultPeriodSelector(self.getParameters(), sCurPeriod)
549 sHtmlTimeWalker = self._generateTimeWalker(self.getParameters(), tsEffective, sCurPeriod);
550
551 if cItems > 0:
552 sHtmlPager = self._generatePagesSelector(self.getParameters(), cItems, cItemsPerPage, iPage)
553 sHtmlItemsPerPageSelector = self._generateItemPerPageSelector(self.getParameters(), cItemsPerPage)
554 else:
555 sHtmlPager = ''
556 sHtmlItemsPerPageSelector = ''
557
558 # Generate navigation bar
559 sHtml = '<table width=100%>\n' \
560 '<tr>\n' \
561 ' <td width=30%>' + sHtmlMemberSelector + '</td>\n' \
562 ' <td width=40% align=center>' + sHtmlTimeWalker + '</td>' \
563 ' <td width=30% align=right>\n' + sHtmlPeriodSelector + '</td>\n' \
564 '</tr>\n' \
565 '<tr>\n' \
566 ' <td width=30%>' + sHtmlStatusSelector + '</td>\n' \
567 ' <td width=40% align=center>\n' + sHtmlPager + '</td>\n' \
568 ' <td width=30% align=right>\n' + sHtmlItemsPerPageSelector + '</td>\n'\
569 '</tr>\n' \
570 '</table>\n'
571
572 return sHtml
573
574 def _generateReportNavigation(self, tsEffective, cHoursPerPeriod, cPeriods):
575 """ Make time navigation bar for the reports. """
576
577 # The period length selector.
578 dParams = self.getParameters();
579 if WuiMain.ksParamReportPeriodInHours in dParams:
580 del dParams[WuiMain.ksParamReportPeriodInHours];
581 sHtmlPeriodLength = '';
582 sHtmlPeriodLength += '<form name="ReportPeriodInHoursForm" method="GET">\n' \
583 ' Period length <select name="%s" onchange="window.location=\'?%s&%s=\' + ' \
584 'this.options[this.selectedIndex].value;" title="Statistics period length in hours.">\n' \
585 % (WuiMain.ksParamReportPeriodInHours,
586 webutils.encodeUrlParams(dParams),
587 WuiMain.ksParamReportPeriodInHours)
588 for cHours in [ 2, 3, 4, 5, 6, 7, 8, 9, 12, 18, 24, 48, 72, 96, 120, 144, 168 ]:
589 sHtmlPeriodLength += ' <option value="%d"%s>%d hours</option>\n' \
590 % (cHours, 'selected="selected"' if cHours == cHoursPerPeriod else '', cHours);
591 sHtmlPeriodLength += ' </select>\n' \
592 '</form>\n'
593
594 # The period count selector.
595 dParams = self.getParameters();
596 if WuiMain.ksParamReportPeriods in dParams:
597 del dParams[WuiMain.ksParamReportPeriods];
598 sHtmlCountOfPeriods = '';
599 sHtmlCountOfPeriods += '<form name="ReportPeriodsForm" method="GET">\n' \
600 ' Periods <select name="%s" onchange="window.location=\'?%s&%s=\' + ' \
601 'this.options[this.selectedIndex].value;" title="Statistics periods to report.">\n' \
602 % (WuiMain.ksParamReportPeriods,
603 webutils.encodeUrlParams(dParams),
604 WuiMain.ksParamReportPeriods)
605 for cCurPeriods in range(2, 43):
606 sHtmlCountOfPeriods += ' <option value="%d"%s>%d</option>\n' \
607 % (cCurPeriods, 'selected="selected"' if cCurPeriods == cPeriods else '', cCurPeriods);
608 sHtmlCountOfPeriods += ' </select>\n' \
609 '</form>\n'
610
611 # The time walker.
612 sHtmlTimeWalker = self._generateTimeWalker(self.getParameters(), tsEffective, '%d hours' % (cHoursPerPeriod));
613
614 # Combine them all.
615 sHtml = '<table width=100%>\n' \
616 ' <tr>\n' \
617 ' <td width=30% align="center">\n' + sHtmlPeriodLength + '</td>\n' \
618 ' <td width=40% align="center">\n' + sHtmlTimeWalker + '</td>' \
619 ' <td width=30% align="center">\n' + sHtmlCountOfPeriods + '</td>\n' \
620 ' </tr>\n' \
621 '</table>\n';
622 return sHtml;
623
624 #
625 # The rest of stuff
626 #
627
628 def _actionGroupedResultsListing( #pylint: disable=R0914
629 self,
630 enmResultsGroupingType,
631 oResultsLogicType,
632 oResultsListContentType):
633 """
634 Override generic listing action.
635
636 oLogicType implements fetchForListing.
637 oListContentType is a child of WuiListContentBase.
638 """
639 cItemsPerPage = self.getIntParam(self.ksParamItemsPerPage, iMin = 2, iMax = 9999, iDefault = 128)
640 iPage = self.getIntParam(self.ksParamPageNo, iMin = 0, iMax = 999999, iDefault = 0)
641 tsEffective = self.getEffectiveDateParam()
642 iGroupMemberId = self.getIntParam(self.ksParamGroupMemberId, iMin = -1, iMax = 999999, iDefault = -1)
643 fOnlyFailures = self.getBoolParam(self.ksParamOnlyFailures, fDefault = False);
644
645 # Get testing results period and validate it
646 asValidValues = [x for (x, _, _) in self.kaoResultPeriods]
647 sCurPeriod = self.getStringParam(self.ksParamEffectivePeriod, asValidValues = asValidValues,
648 sDefault = self.ksResultPeriodDefault)
649 assert sCurPeriod != ''; # Impossible!
650
651 self._checkForUnknownParameters()
652
653 #
654 # Fetch the group members.
655 #
656 # If no grouping is selected, we'll fill the the grouping combo with
657 # testboxes just to avoid having completely useless combo box.
658 #
659 oTrLogic = TestResultLogic(self._oDb);
660 sAltSelectorAction = None;
661 if enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeNone \
662 or enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeTestBox:
663 aoTmp = oTrLogic.getTestBoxes(tsNow = tsEffective, sPeriod = sCurPeriod)
664 aoGroupMembers = sorted(list(set([ (x.idTestBox, '%s (%s)' % (x.sName, str(x.ip))) for x in aoTmp ])),
665 reverse = False, key = lambda asData: asData[1])
666
667 if enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeTestBox:
668 self._sPageTitle = 'Grouped by Test Box';
669 else:
670 self._sPageTitle = 'Ungrouped results';
671 sAltSelectorAction = self.ksActionResultsGroupedByTestBox;
672 aoGroupMembers.insert(0, [None, None]); # The "All" member.
673
674 elif enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeTestGroup:
675 aoTmp = oTrLogic.getTestGroups(tsNow = tsEffective, sPeriod = sCurPeriod);
676 aoGroupMembers = sorted(list(set([ (x.idTestGroup, x.sName ) for x in aoTmp ])),
677 reverse = False, key = lambda asData: asData[1])
678 self._sPageTitle = 'Grouped by Test Group'
679
680 elif enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeBuildRev:
681 aoTmp = oTrLogic.getBuilds(tsNow = tsEffective, sPeriod = sCurPeriod)
682 aoGroupMembers = sorted(list(set([ (x.iRevision, '%s.%d' % (x.oCat.sBranch, x.iRevision)) for x in aoTmp ])),
683 reverse = True, key = lambda asData: asData[0])
684 self._sPageTitle = 'Grouped by Build'
685
686 elif enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeTestCase:
687 aoTmp = oTrLogic.getTestCases(tsNow = tsEffective, sPeriod = sCurPeriod)
688 aoGroupMembers = sorted(list(set([ (x.idTestCase, '%s' % x.sName) for x in aoTmp ])),
689 reverse = False, key = lambda asData: asData[1])
690 self._sPageTitle = 'Grouped by Test Case'
691
692 elif enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeSchedGroup:
693 aoTmp = oTrLogic.getSchedGroups(tsNow = tsEffective, sPeriod = sCurPeriod)
694 aoGroupMembers = sorted(list(set([ (x.idSchedGroup, '%s' % x.sName) for x in aoTmp ])),
695 reverse = False, key = lambda asData: asData[1])
696 self._sPageTitle = 'Grouped by Scheduling Group'
697
698 else:
699 raise TMExceptionBase('Unknown grouping type')
700
701 _sPageBody = ''
702 oContent = None
703 cEntriesMax = 0
704 _dParams = self.getParameters()
705 for idMember, sMemberName in aoGroupMembers:
706 #
707 # Count and fetch entries to be displayed.
708 #
709
710 # Skip group members that were not specified.
711 if idMember != iGroupMemberId \
712 and ( (idMember is not None and enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeNone)
713 or (iGroupMemberId > 0 and enmResultsGroupingType != TestResultLogic.ksResultsGroupingTypeNone) ):
714 continue
715
716 oResultLogic = oResultsLogicType(self._oDb);
717 cEntries = oResultLogic.getEntriesCount(tsNow = tsEffective,
718 sInterval = sCurPeriod,
719 enmResultsGroupingType = enmResultsGroupingType,
720 iResultsGroupingValue = idMember,
721 fOnlyFailures = fOnlyFailures);
722 if cEntries == 0: # Do not display empty groups
723 continue
724 aoEntries = oResultLogic.fetchResultsForListing(iPage * cItemsPerPage,
725 cItemsPerPage,
726 tsNow = tsEffective,
727 sInterval = sCurPeriod,
728 enmResultsGroupingType = enmResultsGroupingType,
729 iResultsGroupingValue = idMember,
730 fOnlyFailures = fOnlyFailures)
731
732 cEntriesMax = max(cEntriesMax, cEntries)
733
734 #
735 # Format them.
736 #
737 oContent = oResultsListContentType(aoEntries,
738 cEntries,
739 iPage,
740 cItemsPerPage,
741 tsEffective,
742 fnDPrint = self._oSrvGlue.dprint,
743 oDisp = self)
744
745 (_, sHtml) = oContent.show(fShowNavigation = False)
746 if sMemberName is not None:
747 _sPageBody += '<table width=100%><tr><td>'
748
749 _dParams[self.ksParamGroupMemberId] = idMember
750 sLink = WuiTmLink(sMemberName, '', _dParams, fBracketed = False).toHtml()
751
752 _sPageBody += '<h2>%s (%d)</h2></td>' % (sLink, cEntries)
753 _sPageBody += '<td><br></td>'
754 _sPageBody += '</tr></table>'
755 _sPageBody += sHtml
756 _sPageBody += '<br>'
757
758 #
759 # Complete the page by slapping navigation controls at the top and
760 # bottom of it.
761 #
762 sHtmlNavigation = self._generateResultNavigation(cEntriesMax, cItemsPerPage, iPage,
763 tsEffective, sCurPeriod, fOnlyFailures,
764 self._generateGroupContentSelector(aoGroupMembers, iGroupMemberId,
765 sAltSelectorAction));
766 if cEntriesMax > 0:
767 self._sPageBody = sHtmlNavigation + _sPageBody + sHtmlNavigation;
768 else:
769 self._sPageBody = sHtmlNavigation + '<p align="center"><i>No data to display</i></p>\n';
770 return True;
771
772 def _generatePage(self):
773 """Override parent handler in order to change page title."""
774 if self._sPageTitle is not None:
775 self._sPageTitle = 'Test Results - ' + self._sPageTitle
776
777 return WuiDispatcherBase._generatePage(self)
778
779 def actionTestResultDetails(self):
780 """Show test case execution result details."""
781 from testmanager.webui.wuitestresult import WuiTestResult;
782
783 self._sTemplate = 'template-details.html';
784 idTestSet = self.getIntParam(TestSetData.ksParam_idTestSet);
785 self._checkForUnknownParameters()
786
787 oTestSetData = TestSetData().initFromDbWithId(self._oDb, idTestSet);
788 try:
789 (oTestResultTree, _) = TestResultLogic(self._oDb).fetchResultTree(idTestSet);
790 except TMTooManyRows:
791 (oTestResultTree, _) = TestResultLogic(self._oDb).fetchResultTree(idTestSet, 2);
792 oBuildDataEx = BuildDataEx().initFromDbWithId(self._oDb, oTestSetData.idBuild, oTestSetData.tsCreated);
793 try: oBuildValidationKitDataEx = BuildDataEx().initFromDbWithId(self._oDb, oTestSetData.idBuildTestSuite,
794 oTestSetData.tsCreated);
795 except: oBuildValidationKitDataEx = None;
796 oTestBoxData = TestBoxData().initFromDbWithGenId(self._oDb, oTestSetData.idGenTestBox);
797 oTestGroupData = TestGroupData().initFromDbWithId(self._oDb, ## @todo This bogus time wise. Bad DB design?
798 oTestSetData.idTestGroup, oTestSetData.tsCreated);
799 oTestCaseDataEx = TestCaseDataEx().initFromDbWithGenId(self._oDb, oTestSetData.idGenTestCase,
800 oTestSetData.tsConfig);
801 oTestCaseArgsDataEx = TestCaseArgsDataEx().initFromDbWithGenIdEx(self._oDb, oTestSetData.idGenTestCaseArgs,
802 oTestSetData.tsConfig);
803
804 oContent = WuiTestResult(oDisp = self, fnDPrint = self._oSrvGlue.dprint);
805 (self._sPageTitle, self._sPageBody) = oContent.showTestCaseResultDetails(oTestResultTree,
806 oTestSetData,
807 oBuildDataEx,
808 oBuildValidationKitDataEx,
809 oTestBoxData,
810 oTestGroupData,
811 oTestCaseDataEx,
812 oTestCaseArgsDataEx);
813 return True
814
815 def actionViewLog(self):
816 """
817 Log viewer action.
818 """
819 from testmanager.webui.wuilogviewer import WuiLogViewer;
820 self._sTemplate = 'template-details.html'; ## @todo create new template (background color, etc)
821 idTestSet = self.getIntParam(self.ksParamLogSetId, iMin = 1);
822 idLogFile = self.getIntParam(self.ksParamLogFileId, iMin = 0, iDefault = 0);
823 cbChunk = self.getIntParam(self.ksParamLogChunkSize, iMin = 256, iMax = 16777216, iDefault = 65536);
824 iChunk = self.getIntParam(self.ksParamLogChunkNo, iMin = 0,
825 iMax = config.g_kcMbMaxMainLog * 1048576 / cbChunk, iDefault = 0);
826 self._checkForUnknownParameters();
827
828 oTestSet = TestSetData().initFromDbWithId(self._oDb, idTestSet);
829 if idLogFile == 0:
830 oTestFile = TestResultFileDataEx().initFakeMainLog(oTestSet);
831 else:
832 oTestFile = TestSetLogic(self._oDb).getFile(idTestSet, idLogFile);
833 if oTestFile.sMime not in [ 'text/plain',]:
834 raise WuiException('The log view does not display files of type: %s' % (oTestFile.sMime,));
835
836 oContent = WuiLogViewer(oTestSet, oTestFile, cbChunk, iChunk, oDisp = self, fnDPrint = self._oSrvGlue.dprint);
837 (self._sPageTitle, self._sPageBody) = oContent.show();
838 return True;
839
840 def actionGetFile(self):
841 """
842 Get file action.
843 """
844 idTestSet = self.getIntParam(self.ksParamGetFileSetId, iMin = 1);
845 idFile = self.getIntParam(self.ksParamGetFileId, iMin = 0, iDefault = 0);
846 fDownloadIt = self.getBoolParam(self.ksParamGetFileDownloadIt, fDefault = True);
847 self._checkForUnknownParameters();
848
849 #
850 # Get the file info and open it.
851 #
852 oTestSet = TestSetData().initFromDbWithId(self._oDb, idTestSet);
853 if idFile == 0:
854 oTestFile = TestResultFileDataEx().initFakeMainLog(oTestSet);
855 else:
856 oTestFile = TestSetLogic(self._oDb).getFile(idTestSet, idFile);
857
858 (oFile, oSizeOrError, _) = oTestSet.openFile(oTestFile.sFile, 'rb');
859 if oFile is None:
860 raise Exception(oSizeOrError);
861
862 #
863 # Send the file.
864 #
865 self._oSrvGlue.setHeaderField('Content-Type', oTestFile.getMimeWithEncoding());
866 if fDownloadIt:
867 self._oSrvGlue.setHeaderField('Content-Disposition', 'attachment; filename="TestSet-%d-%s"'
868 % (idTestSet, oTestFile.sFile,));
869 while True:
870 abChunk = oFile.read(262144);
871 if len(abChunk) == 0:
872 break;
873 self._oSrvGlue.writeRaw(abChunk);
874 return self.ksDispatchRcAllDone;
875
876 def _actionGenericReport(self, oModelType, oReportType):
877 """
878 Generic report action.
879 oReportType is a child of WuiReportContentBase.
880 oModelType is a child of ReportModelBase.
881 """
882 tsEffective = self.getEffectiveDateParam();
883 cPeriods = self.getIntParam(self.ksParamReportPeriods, iMin = 2, iMax = 99, iDefault = 7);
884 cHoursPerPeriod = self.getIntParam(self.ksParamReportPeriodInHours, iMin = 1, iMax = 168, iDefault = 24);
885 sSubject = self.getStringParam(self.ksParamReportSubject, ReportModelBase.kasSubjects,
886 ReportModelBase.ksSubEverything);
887 if sSubject == ReportModelBase.ksSubEverything:
888 aidSubjects = self.getListOfIntParams(self.ksParamReportSubjectIds, aiDefaults = []);
889 else:
890 aidSubjects = self.getListOfIntParams(self.ksParamReportSubjectIds, iMin = 1);
891 if aidSubjects is None:
892 raise WuiException('Missing parameter %s' % (self.ksParamReportSubjectIds,));
893 self._checkForUnknownParameters();
894
895 dParams = \
896 {
897 self.ksParamEffectiveDate: tsEffective,
898 self.ksParamReportPeriods: cPeriods,
899 self.ksParamReportPeriodInHours: cHoursPerPeriod,
900 self.ksParamReportSubject: sSubject,
901 self.ksParamReportSubjectIds: aidSubjects,
902 };
903
904 oModel = oModelType(self._oDb, tsEffective, cPeriods, cHoursPerPeriod, sSubject, aidSubjects);
905 oContent = oReportType(oModel, dParams, fSubReport = False, fnDPrint = self._oSrvGlue.dprint, oDisp = self);
906 (self._sPageTitle, self._sPageBody) = oContent.show();
907 sNavi = self._generateReportNavigation(tsEffective, cHoursPerPeriod, cPeriods);
908 self._sPageBody = sNavi + self._sPageBody;
909 return True;
910
911 def _actionGraphWiz(self):
912 """
913 Graph wizard action.
914 """
915 from testmanager.webui.wuigraphwiz import WuiGraphWiz;
916 self._sTemplate = 'template-graphwiz.html';
917
918 tsEffective = self.getEffectiveDateParam();
919 cPeriods = self.getIntParam(self.ksParamReportPeriods, iMin = 1, iMax = 1, iDefault = 1); # Not needed yet.
920 sTmp = self.getStringParam(self.ksParamReportPeriodInHours, sDefault = '3 weeks');
921 (cHoursPerPeriod, sError) = utils.parseIntervalHours(sTmp);
922 if sError is not None: raise WuiException(sError);
923 asSubjectIds = self.getListOfStrParams(self.ksParamReportSubjectIds);
924 sSubject = self.getStringParam(self.ksParamReportSubject, [ReportModelBase.ksSubEverything],
925 ReportModelBase.ksSubEverything); # dummy
926 aidTestBoxes = self.getListOfIntParams(self.ksParamGraphWizTestBoxIds, iMin = 1, aiDefaults = []);
927 aidBuildCats = self.getListOfIntParams(self.ksParamGraphWizBuildCatIds, iMin = 1, aiDefaults = []);
928 aidTestCases = self.getListOfIntParams(self.ksParamGraphWizTestCaseIds, iMin = 1, aiDefaults = []);
929 fSepTestVars = self.getBoolParam(self.ksParamGraphWizSepTestVars, fDefault = False);
930
931 enmGraphImpl = self.getStringParam(self.ksParamGraphWizImpl, asValidValues = self.kasGraphWizImplValid,
932 sDefault = self.ksGraphWizImpl_Default);
933 cx = self.getIntParam(self.ksParamGraphWizWidth, iMin = 128, iMax = 8192, iDefault = 1280);
934 cy = self.getIntParam(self.ksParamGraphWizHeight, iMin = 128, iMax = 8192, iDefault = int(cx * 5 / 16) );
935 cDotsPerInch = self.getIntParam(self.ksParamGraphWizDpi, iMin = 64, iMax = 512, iDefault = 96);
936 cPtFont = self.getIntParam(self.ksParamGraphWizFontSize, iMin = 6, iMax = 32, iDefault = 8);
937 fErrorBarY = self.getBoolParam(self.ksParamGraphWizErrorBarY, fDefault = False);
938 cMaxErrorBarY = self.getIntParam(self.ksParamGraphWizMaxErrorBarY, iMin = 8, iMax = 9999999, iDefault = 18);
939 cMaxPerGraph = self.getIntParam(self.ksParamGraphWizMaxPerGraph, iMin = 1, iMax = 24, iDefault = 8);
940 fXkcdStyle = self.getBoolParam(self.ksParamGraphWizXkcdStyle, fDefault = False);
941 fTabular = self.getBoolParam(self.ksParamGraphWizTabular, fDefault = False);
942 idSrcTestSet = self.getIntParam(self.ksParamGraphWizSrcTestSetId, iDefault = None);
943 self._checkForUnknownParameters();
944
945 dParams = \
946 {
947 self.ksParamEffectiveDate: tsEffective,
948 self.ksParamReportPeriods: cPeriods,
949 self.ksParamReportPeriodInHours: cHoursPerPeriod,
950 self.ksParamReportSubject: sSubject,
951 self.ksParamReportSubjectIds: asSubjectIds,
952 self.ksParamGraphWizTestBoxIds: aidTestBoxes,
953 self.ksParamGraphWizBuildCatIds: aidBuildCats,
954 self.ksParamGraphWizTestCaseIds: aidTestCases,
955 self.ksParamGraphWizSepTestVars: fSepTestVars,
956
957 self.ksParamGraphWizImpl: enmGraphImpl,
958 self.ksParamGraphWizWidth: cx,
959 self.ksParamGraphWizHeight: cy,
960 self.ksParamGraphWizDpi: cDotsPerInch,
961 self.ksParamGraphWizFontSize: cPtFont,
962 self.ksParamGraphWizErrorBarY: fErrorBarY,
963 self.ksParamGraphWizMaxErrorBarY: cMaxErrorBarY,
964 self.ksParamGraphWizMaxPerGraph: cMaxPerGraph,
965 self.ksParamGraphWizXkcdStyle: fXkcdStyle,
966 self.ksParamGraphWizTabular: fTabular,
967 self.ksParamGraphWizSrcTestSetId: idSrcTestSet,
968 };
969
970 oModel = ReportGraphModel(self._oDb, tsEffective, cPeriods, cHoursPerPeriod, sSubject, asSubjectIds,
971 aidTestBoxes, aidBuildCats, aidTestCases, fSepTestVars);
972 oContent = WuiGraphWiz(oModel, dParams, fSubReport = False, fnDPrint = self._oSrvGlue.dprint, oDisp = self);
973 (self._sPageTitle, self._sPageBody) = oContent.show();
974 return True;
975
976 def _actionVcsHistoryTooltip(self):
977 """
978 Version control system history.
979 """
980 self._sTemplate = 'template-tooltip.html';
981 from testmanager.webui.wuivcshistory import WuiVcsHistoryTooltip;
982
983 iRevision = self.getIntParam(self.ksParamVcsHistoryRevision, iMin = 0, iMax = 999999999);
984 sRepository = self.getStringParam(self.ksParamVcsHistoryRepository);
985 cEntries = self.getIntParam(self.ksParamVcsHistoryEntries, iMin = 1, iMax = 1024, iDefault = 8);
986 self._checkForUnknownParameters();
987
988 aoEntries = VcsRevisionLogic(self._oDb).fetchTimeline(sRepository, iRevision, cEntries);
989 oContent = WuiVcsHistoryTooltip(aoEntries, sRepository, iRevision, cEntries,
990 fnDPrint = self._oSrvGlue.dprint, oDisp = self);
991 (self._sPageTitle, self._sPageBody) = oContent.show();
992 return True;
993
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