wuimain.py revision cf22150eaeeb72431bf1cf65c309a431454fb22b
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# -*- coding: utf-8 -*-
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncTest Manager Core - WUI - The Main page.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCopyright (C) 2012-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThis file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncavailable from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncyou can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncGeneral Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncFoundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynchope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThe contents of this file may alternatively be used under the terms
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncof the Common Development and Distribution License Version 1.0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync(CDDL) only, as it comes in the "COPYING.CDDL" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVirtualBox OSE distribution, in which case the provisions of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCDDL are applicable instead of those of the GPL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncYou may elect to license modified versions of this file under the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncterms and conditions of either the GPL or the CDDL or both.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Standard Python imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Validation Kit imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.webui.wuibase import WuiDispatcherBase, WuiException;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.webui.wuicontentbase import WuiTmLink;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.core.report import ReportLazyModel, ReportGraphModel, ReportModelBase;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.core.testresults import TestResultLogic, TestResultFileDataEx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.core.base import TMExceptionBase, TMTooManyRows;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.core.testset import TestSetData, TestSetLogic;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.core.testgroup import TestGroupData;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.core.testcase import TestCaseDataEx
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.core.testcaseargs import TestCaseArgsDataEx
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.core.vcsrevisions import VcsRevisionLogic;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WUI Main page.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Note! All cylic dependency avoiance stuff goes here in the dispatcher code,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync not in the action specific code. This keeps the uglyness in one place
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync and reduces load time dependencies in the more critical code path.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## The name of the script.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @name Actions
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ksActionResultsGroupedBySchedGroup = 'ResultsGroupedBySchedGroup'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ksActionResultsGroupedByTestGroup = 'ResultsGroupedByTestGroup'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ksActionResultsGroupedByBuildRev = 'ResultsGroupedByBuildRev'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ksActionResultsGroupedByTestBox = 'ResultsGroupedByTestBox'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ksActionResultsGroupedByTestCase = 'ResultsGroupedByTestCase'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ksActionReportFailureReasons = 'ReportFailureReasons';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @name Standard report parameters
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @name Graph Wizard parameters
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## Common parameters: ksParamReportPeriods, ksParamReportPeriodInHours, ksParamReportSubjectIds,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## ksParamReportSubject, ksParamEffectivePeriod, and ksParamEffectiveDate.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @name Graph implementations values for ksParamGraphWizImpl.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync kasGraphWizImplValid = [ ksGraphWizImpl_Default, ksGraphWizImpl_Matplotlib, ksGraphWizImpl_Charts];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ( ksGraphWizImpl_Matplotlib, 'Matplotlib (server)' ),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ( ksGraphWizImpl_Charts, 'Google Charts (client)'),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @name Log Viewer parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @name File getter parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @name VCS history parameters.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## Effective time period. one of the first column values in kaoResultPeriods.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## If this param is specified, then show only results for this member when results grouped by some parameter.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## Optional parameter for indicating whether to restrict the listing to failures only.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## Test result period values.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ( '1 month', 'One month', 31 * 24 ), # The approx hour count varies with the start date.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ( '2 months', 'Two month', (31 + 31) * 24 ), # Using maximum values.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ( '3 months', 'Three month', (31 + 30 + 31) * 24 ),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ( '6 months', 'Six month', (31 + 31 + 30 + 31 + 30 + 31) * 24 ),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## The default test result period.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiDispatcherBase.__init__(self, oSrvGlue, self.ksScriptName);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Populate the action dispatcher dictionary.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Use short form to avoid hitting the right margin (130) when using lambda.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuitestresult import WuiGroupedResultList;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync #d[self.ksActionResultsUnGrouped] = lambda: self._actionResultsListing(TestResultLogic, WuiGroupedResultList)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionResultsUnGrouped] = lambda: self._actionGroupedResultsListing(
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionResultsGroupedByTestGroup] = lambda: self._actionGroupedResultsListing(
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionResultsGroupedByBuildRev] = lambda: self._actionGroupedResultsListing(
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionResultsGroupedByTestBox] = lambda: self._actionGroupedResultsListing(
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionResultsGroupedByTestCase] = lambda: self._actionGroupedResultsListing(
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionResultsGroupedBySchedGroup] = lambda: self._actionGroupedResultsListing(
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionTestResultDetails] = self.actionTestResultDetails
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuireport import WuiReportSummary, WuiReportSuccessRate, WuiReportFailureReasons;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionReportSummary] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportSummary);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionReportRate] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportSuccessRate);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionReportFailureReasons] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportFailureReasons);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync d[self.ksActionVcsHistoryTooltip] = self._actionVcsHistoryTooltip;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Popupate the menus.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Additional URL parameters keeping for time navigation.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if dCurParams is not None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync asActionUrlExtras = [ self.ksParamItemsPerPage, self.ksParamEffectiveDate, self.ksParamEffectivePeriod, ];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sExtraTimeNav += '&%s' % webutils.encodeUrlParams({sExtraParam: dCurParams[sExtraParam]})
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Shorthand to keep within margins.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'Inbox', sActUrlBase + 'TODO', ## @todo list of failures that needs categorizing.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'Reports', sActUrlBase + self.ksActionReportSummary,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Summary', sActUrlBase + self.ksActionReportSummary ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Success Rate', sActUrlBase + self.ksActionReportRate ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Failure Reasons', sActUrlBase + self.ksActionReportFailureReasons ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'Test Results', sActUrlBase + self.ksActionResultsUnGrouped + sExtraTimeNav,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Ungrouped results', sActUrlBase + self.ksActionResultsUnGrouped + sExtraTimeNav ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Grouped by Scheduling Group', sActUrlBase + self.ksActionResultsGroupedBySchedGroup + sExtraTimeNav ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Grouped by Test Group', sActUrlBase + self.ksActionResultsGroupedByTestGroup + sExtraTimeNav ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Grouped by TestBox', sActUrlBase + self.ksActionResultsGroupedByTestBox + sExtraTimeNav ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Grouped by Test Case', sActUrlBase + self.ksActionResultsGroupedByTestCase + sExtraTimeNav ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync [ 'Grouped by Revision', sActUrlBase + self.ksActionResultsGroupedByBuildRev + sExtraTimeNav ],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '> Admin', 'admin.py?' + webutils.encodeUrlParams(self._dDbgParams), []
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """Show the default admin page."""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuitestresult import WuiGroupedResultList;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return self._actionGroupedResultsListing(TestResultLogic.ksResultsGroupingTypeNone,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Navigation bar stuff
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generateStatusSelector(self, dParams, fOnlyFailures):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generate HTML code for the status code selector. Currently very simple.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dParams[self.ksParamOnlyFailures] = not fOnlyFailures;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return WuiTmLink('Show all results' if fOnlyFailures else 'Only show failed tests', '', dParams,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generateTimeSelector(self, dParams, sPreamble, sPostamble):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generate HTML code for time selector.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if WuiDispatcherBase.ksParamEffectiveDate in dParams:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync tsEffective = dParams[WuiDispatcherBase.ksParamEffectiveDate]
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync del dParams[WuiDispatcherBase.ksParamEffectiveDate]
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Forget about page No when changing a period
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlTimeSelector = '<form name="TimeForm" method="GET">\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlTimeSelector += '\n <select name="%s" onchange="window.location=' % WuiDispatcherBase.ksParamEffectiveDate
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlTimeSelector += '\'?%s&%s=\' + ' % (webutils.encodeUrlParams(dParams), WuiDispatcherBase.ksParamEffectiveDate)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlTimeSelector += 'this.options[this.selectedIndex].value;" title="Effective date">\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ('+0000-00-00 00:00:00.00', 'Now', ' title="Present Day. Present Time."'), # lain :)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ('-0000-00-00 03:00:00.00', 'Three hours ago', ''),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ('-0000-00-21 00:00:00.00', 'Three weeks ago', ''),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ('-0000-03-00 00:00:00.00', 'Three months ago', ''),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ('-0000-04-00 00:00:00.00', 'Four months ago', ''),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ('-0000-05-00 00:00:00.00', 'Five months ago', ''),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ('-0000-06-00 00:00:00.00', 'Half a year ago', ''),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for sTimestamp, sWayBackPointCaption, sExtraAttrs in aoWayBackPoints:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlTimeSelector += ' <option value="%s"%s%s>%s</option>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' selected="selected"' if sTimestamp == tsEffective else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlTimeSelector += ' <option value="%s" selected>%s</option>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generateTimeWalker(self, dParams, tsEffective, sCurPeriod):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generates HTML code for walking back and forth in time.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Have to do some math here. :-/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._oDb.execute('SELECT CURRENT_TIMESTAMP - \'' + sCurPeriod + '\'::interval');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._oDb.execute('SELECT %s::TIMESTAMP - \'' + sCurPeriod + '\'::interval,\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' %s::TIMESTAMP + \'' + sCurPeriod + '\'::interval',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Forget about page No when changing a period
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dParams[WuiDispatcherBase.ksParamEffectiveDate] = str(tsPrev);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sPrev = '<a href="?%s" title="One period earlier"><<</a> ' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if tsNext is not None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dParams[WuiDispatcherBase.ksParamEffectiveDate] = str(tsNext);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sNext = ' <a href="?%s" title="One period later">>></a>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return self._generateTimeSelector(self.getParameters(), sPrev, sNext);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generateResultPeriodSelector(self, dParams, sCurPeriod):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generate HTML code for result period selector.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Forget about page No when changing a period
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPeriodSelector = '<form name="PeriodForm" method="GET">\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPeriodSelector += ' <select name="%s" onchange="window.location=' % self.ksParamEffectivePeriod
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPeriodSelector += '\'?%s&%s=\' + ' % (webutils.encodeUrlParams(dParams), self.ksParamEffectivePeriod)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPeriodSelector += 'this.options[this.selectedIndex].value;">\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for sPeriodValue, sPeriodCaption, _ in self.kaoResultPeriods:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPeriodSelector += ' <option value="%s"%s>%s</option>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' selected="selected"' if sPeriodValue == sCurPeriod else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</form>\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generateGroupContentSelector(self, aoGroupMembers, iCurrentMember, sAltAction):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generate HTML code for group content selector.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if sAltAction is not None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlSelector = '<form name="GroupContentForm" method="GET">\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlSelector += ' <select name="%s" onchange="window.location=' % self.ksParamGroupMemberId
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlSelector += '\'?%s&%s=\' + ' % (webutils.encodeUrlParams(dParams), self.ksParamGroupMemberId)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlSelector += 'this.options[this.selectedIndex].value;">\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlSelector += '<option value="-1">All</option>\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for iGroupMemberId, sGroupMemberName in aoGroupMembers:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if iGroupMemberId is not None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlSelector += ' <option value="%s"%s>%s</option>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' selected="selected"' if iGroupMemberId == iCurrentMember else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</form>\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generatePagesSelector(self, dParams, cItems, cItemsPerPage, iPage):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generate HTML code for pages (1, 2, 3 ... N) selector
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHrefPtr = '<a href="?%s&%s=' % (webutils.encodeUrlParams(dParams).replace('%', '%%'),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cNumOfPages = (cItems + cItemsPerPage - 1) / cItemsPerPage;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cPagesRangeEnd = cPagesRangeStart + cPagesToDisplay \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if not cPagesRangeStart + cPagesToDisplay > cNumOfPages else cNumOfPages
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Adjust pages range
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # 1 2 3 4...
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPager = ' \n'.join(sHrefPtr % (x, str(x + 1)) if x != iPage else str(x + 1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPager = '%s ... \n' % (sHrefPtr % (0, str(1))) + sHtmlPager
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPager += ' ... %s\n' % (sHrefPtr % (cNumOfPages, str(cNumOfPages + 1)))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Prev/Next (using << >> because « and » are too tiny).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dParams[WuiDispatcherBase.ksParamPageNo] = iPage - 1
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPager = ('<a title="Previous page" href="?%s"><<</a> \n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dParams[WuiDispatcherBase.ksParamPageNo] = iPage + 1
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPager += '\n <a title="Next page" href="?%s">>></a>\n' % (webutils.encodeUrlParams(dParams),)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generateItemPerPageSelector(self, dParams, cItemsPerPage):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generate HTML code for items per page selector
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if WuiDispatcherBase.ksParamItemsPerPage in dParams:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Forced reset of the page number
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlItemsPerPageSelector = '<form name="AgesPerPageForm" method="GET">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' Max <select name="%s" onchange="window.location=\'?%s&%s=\' + ' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'this.options[this.selectedIndex].value;" title="Max items per page">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aiItemsPerPage = [16, 32, 64, 128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlItemsPerPageSelector += ' <option value="%d" %s>%d</option>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'selected="selected"' if iItemsPerPage == cItemsPerPage else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlItemsPerPageSelector += ' </select> items per page\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</form>\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generateResultNavigation(self, cItems, cItemsPerPage, iPage, tsEffective, sCurPeriod, fOnlyFailures,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Make custom time navigation bar for the results. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Generate the elements.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlStatusSelector = self._generateStatusSelector(self.getParameters(), fOnlyFailures);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPeriodSelector = self._generateResultPeriodSelector(self.getParameters(), sCurPeriod)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlTimeWalker = self._generateTimeWalker(self.getParameters(), tsEffective, sCurPeriod);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPager = self._generatePagesSelector(self.getParameters(), cItems, cItemsPerPage, iPage)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlItemsPerPageSelector = self._generateItemPerPageSelector(self.getParameters(), cItemsPerPage)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Generate navigation bar
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=30%>' + sHtmlMemberSelector + '</td>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=40% align=center>' + sHtmlTimeWalker + '</td>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=30% align=right>\n' + sHtmlPeriodSelector + '</td>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</tr>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=30%>' + sHtmlStatusSelector + '</td>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=40% align=center>\n' + sHtmlPager + '</td>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=30% align=right>\n' + sHtmlItemsPerPageSelector + '</td>\n'\
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</tr>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</table>\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _generateReportNavigation(self, tsEffective, cHoursPerPeriod, cPeriods):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Make time navigation bar for the reports. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # The period length selector.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPeriodLength += '<form name="ReportPeriodInHoursForm" method="GET">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' Period length <select name="%s" onchange="window.location=\'?%s&%s=\' + ' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'this.options[this.selectedIndex].value;" title="Statistics period length in hours.">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for cHours in [ 2, 3, 4, 5, 6, 7, 8, 9, 12, 18, 24, 48, 72, 96, 120, 144, 168 ]:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlPeriodLength += ' <option value="%d"%s>%d hours</option>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % (cHours, 'selected="selected"' if cHours == cHoursPerPeriod else '', cHours);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</form>\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # The period count selector.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlCountOfPeriods += '<form name="ReportPeriodsForm" method="GET">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' Periods <select name="%s" onchange="window.location=\'?%s&%s=\' + ' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'this.options[this.selectedIndex].value;" title="Statistics periods to report.">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlCountOfPeriods += ' <option value="%d"%s>%d</option>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % (cCurPeriods, 'selected="selected"' if cCurPeriods == cPeriods else '', cCurPeriods);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</form>\n'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # The time walker.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlTimeWalker = self._generateTimeWalker(self.getParameters(), tsEffective, '%d hours' % (cHoursPerPeriod));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Combine them all.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <tr>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=30% align="center">\n' + sHtmlPeriodLength + '</td>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=40% align="center">\n' + sHtmlTimeWalker + '</td>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <td width=30% align="center">\n' + sHtmlCountOfPeriods + '</td>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </tr>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</table>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # The rest of stuff
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _actionGroupedResultsListing( #pylint: disable=R0914
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Override generic listing action.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oLogicType implements fetchForListing.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oListContentType is a child of WuiListContentBase.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cItemsPerPage = self.getIntParam(self.ksParamItemsPerPage, iMin = 2, iMax = 9999, iDefault = 128)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iPage = self.getIntParam(self.ksParamPageNo, iMin = 0, iMax = 999999, iDefault = 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iGroupMemberId = self.getIntParam(self.ksParamGroupMemberId, iMin = -1, iMax = 999999, iDefault = -1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fOnlyFailures = self.getBoolParam(self.ksParamOnlyFailures, fDefault = False);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Get testing results period and validate it
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync asValidValues = [x for (x, _, _) in self.kaoResultPeriods]
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sCurPeriod = self.getStringParam(self.ksParamEffectivePeriod, asValidValues = asValidValues,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Fetch the group members.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # If no grouping is selected, we'll fill the the grouping combo with
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # testboxes just to avoid having completely useless combo box.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeNone \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync or enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeTestBox:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoTmp = oTrLogic.getTestBoxes(tsNow = tsEffective, sPeriod = sCurPeriod)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoGroupMembers = sorted(list(set([ (x.idTestBox, '%s (%s)' % (x.sName, str(x.ip))) for x in aoTmp ])),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeTestBox:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sAltSelectorAction = self.ksActionResultsGroupedByTestBox;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoGroupMembers.insert(0, [None, None]); # The "All" member.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeTestGroup:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoTmp = oTrLogic.getTestGroups(tsNow = tsEffective, sPeriod = sCurPeriod);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoGroupMembers = sorted(list(set([ (x.idTestGroup, x.sName ) for x in aoTmp ])),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeBuildRev:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoTmp = oTrLogic.getBuilds(tsNow = tsEffective, sPeriod = sCurPeriod)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoGroupMembers = sorted(list(set([ (x.iRevision, '%s.%d' % (x.oCat.sBranch, x.iRevision)) for x in aoTmp ])),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeTestCase:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoTmp = oTrLogic.getTestCases(tsNow = tsEffective, sPeriod = sCurPeriod)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoGroupMembers = sorted(list(set([ (x.idTestCase, '%s' % x.sName) for x in aoTmp ])),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeSchedGroup:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoTmp = oTrLogic.getSchedGroups(tsNow = tsEffective, sPeriod = sCurPeriod)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoGroupMembers = sorted(list(set([ (x.idSchedGroup, '%s' % x.sName) for x in aoTmp ])),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Count and fetch entries to be displayed.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Skip group members that were not specified.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync and ( (idMember is not None and enmResultsGroupingType == TestResultLogic.ksResultsGroupingTypeNone)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync or (iGroupMemberId > 0 and enmResultsGroupingType != TestResultLogic.ksResultsGroupingTypeNone) ):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cEntries = oResultLogic.getEntriesCount(tsNow = tsEffective,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoEntries = oResultLogic.fetchResultsForListing(iPage * cItemsPerPage,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Format them.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (_, sHtml) = oContent.show(fShowNavigation = False)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if sMemberName is not None:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sLink = WuiTmLink(sMemberName, '', _dParams, fBracketed = False).toHtml()
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync _sPageBody += '<h2>%s (%d)</h2></td>' % (sLink, cEntries)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Complete the page by slapping navigation controls at the top and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # bottom of it.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtmlNavigation = self._generateResultNavigation(cEntriesMax, cItemsPerPage, iPage,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._generateGroupContentSelector(aoGroupMembers, iGroupMemberId,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._sPageBody = sHtmlNavigation + _sPageBody + sHtmlNavigation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._sPageBody = sHtmlNavigation + '<p align="center"><i>No data to display</i></p>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """Override parent handler in order to change page title."""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._sPageTitle = 'Test Results - ' + self._sPageTitle
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """Show test case execution result details."""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuitestresult import WuiTestResult;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync idTestSet = self.getIntParam(TestSetData.ksParam_idTestSet);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestSetData = TestSetData().initFromDbWithId(self._oDb, idTestSet);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (oTestResultTree, _) = TestResultLogic(self._oDb).fetchResultTree(idTestSet);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (oTestResultTree, _) = TestResultLogic(self._oDb).fetchResultTree(idTestSet, 2);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oBuildDataEx = BuildDataEx().initFromDbWithId(self._oDb, oTestSetData.idBuild, oTestSetData.tsCreated);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try: oBuildValidationKitDataEx = BuildDataEx().initFromDbWithId(self._oDb, oTestSetData.idBuildTestSuite,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestBoxData = TestBoxData().initFromDbWithGenId(self._oDb, oTestSetData.idGenTestBox);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestGroupData = TestGroupData().initFromDbWithId(self._oDb, ## @todo This bogus time wise. Bad DB design?
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestCaseDataEx = TestCaseDataEx().initFromDbWithGenId(self._oDb, oTestSetData.idGenTestCase,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestCaseArgsDataEx = TestCaseArgsDataEx().initFromDbWithGenIdEx(self._oDb, oTestSetData.idGenTestCaseArgs,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oContent = WuiTestResult(oDisp = self, fnDPrint = self._oSrvGlue.dprint);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (self._sPageTitle, self._sPageBody) = oContent.showTestCaseResultDetails(oTestResultTree,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Log viewer action.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuilogviewer import WuiLogViewer;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._sTemplate = 'template-details.html'; ## @todo create new template (background color, etc)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync idTestSet = self.getIntParam(self.ksParamLogSetId, iMin = 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync idLogFile = self.getIntParam(self.ksParamLogFileId, iMin = 0, iDefault = 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cbChunk = self.getIntParam(self.ksParamLogChunkSize, iMin = 256, iMax = 16777216, iDefault = 65536);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iChunk = self.getIntParam(self.ksParamLogChunkNo, iMin = 0,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iMax = config.g_kcMbMaxMainLog * 1048576 / cbChunk, iDefault = 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestSet = TestSetData().initFromDbWithId(self._oDb, idTestSet);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestFile = TestResultFileDataEx().initFakeMainLog(oTestSet);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestFile = TestSetLogic(self._oDb).getFile(idTestSet, idLogFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WuiException('The log view does not display files of type: %s' % (oTestFile.sMime,));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oContent = WuiLogViewer(oTestSet, oTestFile, cbChunk, iChunk, oDisp = self, fnDPrint = self._oSrvGlue.dprint);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (self._sPageTitle, self._sPageBody) = oContent.show();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Get file action.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync idTestSet = self.getIntParam(self.ksParamGetFileSetId, iMin = 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync idFile = self.getIntParam(self.ksParamGetFileId, iMin = 0, iDefault = 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fDownloadIt = self.getBoolParam(self.ksParamGetFileDownloadIt, fDefault = True);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Get the file info and open it.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestSet = TestSetData().initFromDbWithId(self._oDb, idTestSet);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestFile = TestResultFileDataEx().initFakeMainLog(oTestSet);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestFile = TestSetLogic(self._oDb).getFile(idTestSet, idFile);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (oFile, oSizeOrError, _) = oTestSet.openFile(oTestFile.sFile, 'rb');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Send the file.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._oSrvGlue.setHeaderField('Content-Type', oTestFile.getMimeWithEncoding());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._oSrvGlue.setHeaderField('Content-Disposition', 'attachment; filename="TestSet-%d-%s"'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _actionGenericReport(self, oModelType, oReportType):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generic report action.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oReportType is a child of WuiReportContentBase.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oModelType is a child of ReportModelBase.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cPeriods = self.getIntParam(self.ksParamReportPeriods, iMin = 2, iMax = 99, iDefault = 7);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cHoursPerPeriod = self.getIntParam(self.ksParamReportPeriodInHours, iMin = 1, iMax = 168, iDefault = 24);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sSubject = self.getStringParam(self.ksParamReportSubject, ReportModelBase.kasSubjects,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aidSubjects = self.getListOfIntParams(self.ksParamReportSubjectIds, aiDefaults = []);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aidSubjects = self.getListOfIntParams(self.ksParamReportSubjectIds, iMin = 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync raise WuiException('Missing parameter %s' % (self.ksParamReportSubjectIds,));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oModel = oModelType(self._oDb, tsEffective, cPeriods, cHoursPerPeriod, sSubject, aidSubjects);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oContent = oReportType(oModel, dParams, fSubReport = False, fnDPrint = self._oSrvGlue.dprint, oDisp = self);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (self._sPageTitle, self._sPageBody) = oContent.show();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sNavi = self._generateReportNavigation(tsEffective, cHoursPerPeriod, cPeriods);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Graph wizard action.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuigraphwiz import WuiGraphWiz;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cPeriods = self.getIntParam(self.ksParamReportPeriods, iMin = 1, iMax = 1, iDefault = 1); # Not needed yet.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTmp = self.getStringParam(self.ksParamReportPeriodInHours, sDefault = '3 weeks');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (cHoursPerPeriod, sError) = utils.parseIntervalHours(sTmp);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync asSubjectIds = self.getListOfStrParams(self.ksParamReportSubjectIds);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sSubject = self.getStringParam(self.ksParamReportSubject, [ReportModelBase.ksSubEverything],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aidTestBoxes = self.getListOfIntParams(self.ksParamGraphWizTestBoxIds, iMin = 1, aiDefaults = []);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aidBuildCats = self.getListOfIntParams(self.ksParamGraphWizBuildCatIds, iMin = 1, aiDefaults = []);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aidTestCases = self.getListOfIntParams(self.ksParamGraphWizTestCaseIds, iMin = 1, aiDefaults = []);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSepTestVars = self.getBoolParam(self.ksParamGraphWizSepTestVars, fDefault = False);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmGraphImpl = self.getStringParam(self.ksParamGraphWizImpl, asValidValues = self.kasGraphWizImplValid,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cx = self.getIntParam(self.ksParamGraphWizWidth, iMin = 128, iMax = 8192, iDefault = 1280);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cy = self.getIntParam(self.ksParamGraphWizHeight, iMin = 128, iMax = 8192, iDefault = int(cx * 5 / 16) );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cDotsPerInch = self.getIntParam(self.ksParamGraphWizDpi, iMin = 64, iMax = 512, iDefault = 96);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cPtFont = self.getIntParam(self.ksParamGraphWizFontSize, iMin = 6, iMax = 32, iDefault = 8);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fErrorBarY = self.getBoolParam(self.ksParamGraphWizErrorBarY, fDefault = False);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cMaxErrorBarY = self.getIntParam(self.ksParamGraphWizMaxErrorBarY, iMin = 8, iMax = 9999999, iDefault = 18);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cMaxPerGraph = self.getIntParam(self.ksParamGraphWizMaxPerGraph, iMin = 1, iMax = 24, iDefault = 8);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fXkcdStyle = self.getBoolParam(self.ksParamGraphWizXkcdStyle, fDefault = False);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fTabular = self.getBoolParam(self.ksParamGraphWizTabular, fDefault = False);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync idSrcTestSet = self.getIntParam(self.ksParamGraphWizSrcTestSetId, iDefault = None);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oModel = ReportGraphModel(self._oDb, tsEffective, cPeriods, cHoursPerPeriod, sSubject, asSubjectIds,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aidTestBoxes, aidBuildCats, aidTestCases, fSepTestVars);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oContent = WuiGraphWiz(oModel, dParams, fSubReport = False, fnDPrint = self._oSrvGlue.dprint, oDisp = self);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (self._sPageTitle, self._sPageBody) = oContent.show();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Version control system history.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuivcshistory import WuiVcsHistoryTooltip;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iRevision = self.getIntParam(self.ksParamVcsHistoryRevision, iMin = 0, iMax = 999999999);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sRepository = self.getStringParam(self.ksParamVcsHistoryRepository);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cEntries = self.getIntParam(self.ksParamVcsHistoryEntries, iMin = 1, iMax = 1024, iDefault = 8);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aoEntries = VcsRevisionLogic(self._oDb).fetchTimeline(sRepository, iRevision, cEntries);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oContent = WuiVcsHistoryTooltip(aoEntries, sRepository, iRevision, cEntries,