VirtualBox

Changeset 65054 in vbox for trunk/src/VBox/ValidationKit


Ignore:
Timestamp:
Jan 2, 2017 9:20:49 PM (8 years ago)
Author:
vboxsync
Message:

TestManager: Added filtering to the reports page.

Location:
trunk/src/VBox/ValidationKit/testmanager
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/testmanager/core/report.py

    r62484 r65054  
    3838from testmanager.core.testcase      import TestCaseLogic;
    3939from testmanager.core.testcaseargs  import TestCaseArgsLogic;
     40from testmanager.core.testresults   import TestResultLogic, TestResultFilter;
    4041from common                         import constants;
     42
     43
     44
     45class ReportFilter(TestResultFilter):
     46    """
     47    Same as TestResultFilter for now.
     48    """
     49
     50    def __init__(self):
     51        TestResultFilter.__init__(self);
    4152
    4253
     
    7384
    7485
    75     def __init__(self, oDb, tsNow, cPeriods, cHoursPerPeriod, sSubject, aidSubjects):
     86    def __init__(self, oDb, tsNow, cPeriods, cHoursPerPeriod, sSubject, aidSubjects, oFilter):
    7687        ModelLogicBase.__init__(self, oDb);
    7788        # Public so the report generator can easily access them.
     
    8293        self.sSubject        = sSubject;
    8394        self.aidSubjects     = aidSubjects;
     95        self.oFilter         = oFilter;
    8496
    8597    def getExtraSubjectTables(self):
    8698        """
    87         Returns a string with any extra tables needed by the subject. Each
    88         table name is prefixed by a comma, so can be appended to a FROM
    89         statement.
    90         """
    91         return '';
     99        Returns a list of additional tables needed by the subject.
     100        """
     101        return [];
    92102
    93103    def getExtraSubjectWhereExpr(self):
     
    527537        """
    528538
     539        sBaseQuery  = 'SELECT   TestSets.enmStatus, COUNT(TestSets.idTestSet)\n' \
     540                      'FROM     TestSets\n' \
     541                    + self.oFilter.getTableJoins();
     542        for sTable in self.getExtraSubjectTables():
     543            sBaseQuery = sBaseQuery[:-1] + ',\n         ' + sTable + '\n';
     544        sBaseQuery += 'WHERE    enmStatus <> \'running\'\n' \
     545                    + self.oFilter.getWhereConditions() \
     546                    + self.getExtraSubjectWhereExpr();
     547
    529548        adPeriods = [];
    530549        for iPeriod in xrange(self.cPeriods):
    531             self._oDb.execute('SELECT   enmStatus, COUNT(TestSets.idTestSet)\n'
    532                               'FROM     TestSets' + self.getExtraSubjectTables() +'\n'
    533                               'WHERE    enmStatus <> \'running\'\n'
    534                               + self.getExtraSubjectWhereExpr()
    535                               + self.getExtraWhereExprForPeriod(iPeriod)
    536                               +
    537                               'GROUP BY enmStatus\n');
     550            self._oDb.execute(sBaseQuery + self.getExtraWhereExprForPeriod(iPeriod) + 'GROUP BY enmStatus\n');
    538551
    539552            dRet = \
     
    567580        oFailureReasonLogic = FailureReasonLogic(self._oDb);
    568581
     582        #
    569583        # Create a temporary table
     584        #
    570585        sTsNow   = 'CURRENT_TIMESTAMP' if self.tsNow is None else self._oDb.formatBindArgs('%s::TIMESTAMP', (self.tsNow,));
    571586        sTsFirst = '(%s - interval \'%s hours\')' \
    572587                 % (sTsNow, self.cHoursPerPeriod * self.cPeriods,);
    573         self._oDb.execute('CREATE TEMPORARY TABLE TmpReasons ON COMMIT DROP AS\n'
    574                           'SELECT   TestResultFailures.idFailureReason AS idFailureReason,\n'
    575                           '         TestResultFailures.idTestResult    AS idTestResult,\n'
    576                           '         TestSets.idTestSet                 AS idTestSet,\n'
    577                           '         TestSets.tsDone                    AS tsDone,\n'
    578                           '         TestSets.tsCreated                 AS tsCreated,\n'
    579                           '         TestSets.idBuild                   AS idBuild\n'
    580                           'FROM     TestResultFailures,\n'
    581                           '         TestResults,\n'
    582                           '         TestSets' + self.getExtraSubjectTables() + '\n'
    583                           'WHERE    TestResultFailures.idTestResult = TestResults.idTestResult\n'
    584                           '     AND TestResultFailures.tsExpire     = \'infinity\'::TIMESTAMP\n'
    585                           '     AND TestResultFailures.tsEffective >= ' + sTsFirst + '\n'
    586                           '     AND TestResults.enmStatus          <> \'running\'\n'
    587                           '     AND TestResults.enmStatus          <> \'success\'\n'
    588                           '     AND TestResults.tsCreated          >= ' + sTsFirst + '\n'
    589                           '     AND TestResults.tsCreated          <  ' + sTsNow + '\n'
    590                           '     AND TestResults.idTestSet           = TestSets.idTestSet\n'
    591                           '     AND TestSets.tsDone                >= ' + sTsFirst + '\n'
    592                           '     AND TestSets.tsDone                <  ' + sTsNow + '\n'
    593                           + self.getExtraSubjectWhereExpr());
     588        sQuery   = 'CREATE TEMPORARY TABLE TmpReasons ON COMMIT DROP AS\n' \
     589                   'SELECT   TestResultFailures.idFailureReason AS idFailureReason,\n' \
     590                   '         TestResultFailures.idTestResult    AS idTestResult,\n' \
     591                   '         TestSets.idTestSet                 AS idTestSet,\n' \
     592                   '         TestSets.tsDone                    AS tsDone,\n' \
     593                   '         TestSets.tsCreated                 AS tsCreated,\n' \
     594                   '         TestSets.idBuild                   AS idBuild\n' \
     595                   'FROM     TestResultFailures,\n' \
     596                   '         TestResults,\n' \
     597                   '         TestSets\n' \
     598                   + self.oFilter.getTableJoins(dOmitTables = {'TestResults': True, 'TestResultFailures': True});
     599        for sTable in self.getExtraSubjectTables():
     600            if sTable not in [ 'TestResults', 'TestResultFailures' ] and not self.oFilter.isJoiningWithTable(sTable):
     601                sQuery = sQuery[:-1] + ',\n         ' + sTable + '\n';
     602        sQuery  += 'WHERE    TestResultFailures.idTestResult = TestResults.idTestResult\n' \
     603                   '     AND TestResultFailures.tsExpire     = \'infinity\'::TIMESTAMP\n' \
     604                   '     AND TestResultFailures.tsEffective >= ' + sTsFirst + '\n' \
     605                   '     AND TestResults.enmStatus          <> \'running\'\n' \
     606                   '     AND TestResults.enmStatus          <> \'success\'\n' \
     607                   '     AND TestResults.tsCreated          >= ' + sTsFirst + '\n' \
     608                   '     AND TestResults.tsCreated          <  ' + sTsNow + '\n' \
     609                   '     AND TestResults.idTestSet           = TestSets.idTestSet\n' \
     610                   '     AND TestSets.tsDone                >= ' + sTsFirst + '\n' \
     611                   '     AND TestSets.tsDone                <  ' + sTsNow + '\n' \
     612                   + self.oFilter.getWhereConditions() \
     613                   + self.getExtraSubjectWhereExpr();
     614        self._oDb.execute(sQuery);
    594615        self._oDb.execute('SELECT idFailureReason FROM TmpReasons;');
    595616
     617        #
    596618        # Retrieve the period results.
     619        #
    597620        oSet = ReportFailureReasonSet();
    598621        for iPeriod in xrange(self.cPeriods):
     
    735758        oSet = ReportPeriodSetWithTotalBase(sIdColumn if sIdAttr is None else sIdAttr);
    736759
     760        # Construct base query.
     761        sBaseQuery  = 'SELECT   TestSets.' + sIdColumn + ',\n' \
     762                      '         COUNT(CASE WHEN TestSets.enmStatus >= \'failure\' THEN 1 END),\n' \
     763                      '         MIN(TestSets.tsDone),\n' \
     764                      '         MAX(TestSets.tsDone),\n' \
     765                      '         COUNT(TestSets.idTestResult)\n' \
     766                      'FROM     TestSets\n' \
     767                      + self.oFilter.getTableJoins();
     768        for sTable in self.getExtraSubjectTables():
     769            sBaseQuery = sBaseQuery[:-1] + ',\n         ' + sTable + '\n';
     770        sBaseQuery += 'WHERE    TRUE\n' \
     771                    + self.oFilter.getWhereConditions() \
     772                    + self.getExtraSubjectWhereExpr() + '\n';
     773
    737774        # Retrieve the period results.
    738775        for iPeriod in xrange(self.cPeriods):
    739             self._oDb.execute('SELECT   ' + sIdColumn + ',\n'
    740                               '         COUNT(CASE WHEN enmStatus >= \'failure\' THEN 1 END),\n'
    741                               '         MIN(tsDone),\n'
    742                               '         MAX(tsDone),\n'
    743                               '         COUNT(idTestResult)\n'
    744                               'FROM     TestSets' + self.getExtraSubjectTables() + '\n'
    745                               'WHERE    TRUE\n'
    746                               + self.getExtraWhereExprForPeriod(iPeriod)
    747                               + self.getExtraSubjectWhereExpr() + '\n'
    748                               'GROUP BY ' + sIdColumn + '\n');
     776            self._oDb.execute(sBaseQuery + self.getExtraWhereExprForPeriod(iPeriod) + 'GROUP BY TestSets.' + sIdColumn + '\n');
    749777            aaoRows = self._oDb.fetchAll()
    750778
     
    797825        """
    798826        sSorting = 'ASC' if fEnter else 'DESC';
    799         self._oDb.execute('SELECT   TestSets.idTestResult,\n'
    800                           '         TestSets.idTestSet,\n'
    801                           '         TestSets.tsDone,\n'
    802                           '         TestSets.idBuild,\n'
    803                           '         Builds.iRevision,\n'
    804                           '         BuildCategories.sRepository\n'
    805                           'FROM     TestSets,\n'
    806                           '         Builds,\n'
    807                           '         BuildCategories' + self.getExtraSubjectTables() + '\n'
    808                           'WHERE    TestSets.' + sIdColumn + '      = %s\n'
    809                           '     AND TestSets.idBuild          = Builds.idBuild\n'
    810                           '     AND TestSets.enmStatus       >= \'failure\'\n'
    811                           + self.getExtraWhereExprForPeriod(iPeriod) +
    812                           '     AND Builds.tsExpire           > TestSets.tsCreated\n'
    813                           '     AND Builds.tsEffective       <= TestSets.tsCreated\n'
    814                           '     AND Builds.idBuildCategory    = BuildCategories.idBuildCategory'
    815                           + self.getExtraSubjectWhereExpr() + '\n'
    816                           'ORDER BY Builds.iRevision ' + sSorting + ',\n'
    817                           '         TestSets.tsCreated ' + sSorting + '\n'
    818                           'LIMIT 1\n'
    819                           , ( idSubject, ));
     827        sQuery   = 'SELECT   TestSets.idTestResult,\n' \
     828                   '         TestSets.idTestSet,\n' \
     829                   '         TestSets.tsDone,\n' \
     830                   '         TestSets.idBuild,\n' \
     831                   '         Builds.iRevision,\n' \
     832                   '         BuildCategories.sRepository\n' \
     833                   'FROM     TestSets\n' \
     834                   + self.oFilter.getTableJoins(dOmitTables = {'Builds': True, 'BuildCategories': True});
     835        sQuery   = sQuery[:-1] + ',\n' \
     836                   '         Builds,\n' \
     837                   '         BuildCategories\n';
     838        for sTable in self.getExtraSubjectTables():
     839            if sTable not in [ 'Builds', 'BuildCategories' ] and not self.oFilter.isJoiningWithTable(sTable):
     840                sQuery = sQuery[:-1] + ',\n         ' + sTable + '\n';
     841        sQuery  += 'WHERE    TestSets.' + sIdColumn + '      = ' + str(idSubject) + '\n' \
     842                   '     AND TestSets.idBuild          = Builds.idBuild\n' \
     843                   '     AND TestSets.enmStatus       >= \'failure\'\n' \
     844                   + self.getExtraWhereExprForPeriod(iPeriod) + \
     845                   '     AND Builds.tsExpire           > TestSets.tsCreated\n' \
     846                   '     AND Builds.tsEffective       <= TestSets.tsCreated\n' \
     847                   '     AND Builds.idBuildCategory    = BuildCategories.idBuildCategory\n' \
     848                   + self.oFilter.getWhereConditions() \
     849                   + self.getExtraSubjectWhereExpr() + '\n' \
     850                   'ORDER BY Builds.iRevision ' + sSorting + ',\n' \
     851                   '         TestSets.tsCreated ' + sSorting + '\n' \
     852                   'LIMIT 1\n';
     853        self._oDb.execute(sQuery);
    820854        aoRow = self._oDb.fetchOne();
    821855        if aoRow is None:
     
    826860                                   iPeriod = iPeriod, fEnter = fEnter, idSubject = idSubject, oSubject = oSubject);
    827861
    828 
     862    def fetchPossibleFilterOptions(self, oFilter, tsNow, sPeriod):
     863        """
     864        Fetches possible filtering options.
     865        """
     866        return TestResultLogic(self._oDb).fetchPossibleFilterOptions(oFilter, tsNow, sPeriod);
    829867
    830868
  • trunk/src/VBox/ValidationKit/testmanager/core/testresults.py

    r65053 r65054  
    660660    def __init__(self):
    661661        ModelFilterBase.__init__(self);
    662         oCrit = FilterCriterion('Test status', sVarNm = 'ts', sType = FilterCriterion.ksType_String,
     662        oCrit = FilterCriterion('Test statuses', sVarNm = 'ts', sType = FilterCriterion.ksType_String,
    663663                                sTable = 'TestSets', sColumn = 'enmStatus');
    664         oCrit.aoPossible = (
    665             FilterCriterionValueAndDescription(TestResultData.ksTestStatus_Success,  'Success'),
    666             FilterCriterionValueAndDescription(TestResultData.ksTestStatus_Running,  'Running'),
    667             FilterCriterionValueAndDescription(TestResultData.ksTestStatus_Skipped,  'Skipped'),
    668             FilterCriterionValueAndDescription(TestResultData.ksTestStatus_Aborted,  'Aborted'),
    669             FilterCriterionValueAndDescription(TestResultData.ksTestStatus_Failure,  'Failure'),
    670             FilterCriterionValueAndDescription(TestResultData.ksTestStatus_TimedOut, 'Timed out'),
    671             FilterCriterionValueAndDescription(TestResultData.ksTestStatus_Rebooted, 'Rebooted'),
    672         );
    673664        self.aCriteria.append(oCrit);
    674665        assert self.aCriteria[self.kiTestStatus] is oCrit;
     
    695686        assert self.aCriteria[self.kiRevisions] is oCrit;
    696687
    697         oCrit = FilterCriterion('CPU Arches', sVarNm = 'ca', sTable = 'TestBoxesWithStrings', sColumn = 'idStrCpuArch');
     688        oCrit = FilterCriterion('CPU arches', sVarNm = 'ca', sTable = 'TestBoxesWithStrings', sColumn = 'idStrCpuArch');
    698689        self.aCriteria.append(oCrit);
    699690        assert self.aCriteria[self.kiCpuArches] is oCrit;
    700691
    701         oCrit = FilterCriterion('CPU Vendor', sVarNm = 'cv', sTable = 'TestBoxesWithStrings', sColumn = 'idStrCpuVendor');
     692        oCrit = FilterCriterion('CPU vendors', sVarNm = 'cv', sTable = 'TestBoxesWithStrings', sColumn = 'idStrCpuVendor');
    702693        self.aCriteria.append(oCrit);
    703694        assert self.aCriteria[self.kiCpuVendors] is oCrit;
     
    711702        assert self.aCriteria[self.kiOsVersions] is oCrit;
    712703
    713         oCrit = FilterCriterion('Failure Reasons', sVarNm = 'fr', sTable = 'TestResultFailures', sColumn = 'idFailureReason');
     704        oCrit = FilterCriterion('Failure reasons', sVarNm = 'fr', sTable = 'TestResultFailures', sColumn = 'idFailureReason');
    714705        self.aCriteria.append(oCrit);
    715706        assert self.aCriteria[self.kiFailReasons] is oCrit;
     
    731722        return sQuery;
    732723
    733     def getTableJoins(self, sExtraIndent = '', iOmit = -1):
     724    def getTableJoins(self, sExtraIndent = '', iOmit = -1, dOmitTables = None):
    734725        """
    735726        Construct the WHERE conditions for the filter, optionally omitting one
    736727        criterion.
    737728        """
     729        afDone = { 'TestSets': True, };
     730        if dOmitTables is not None:
     731            afDone.update(dOmitTables);
     732
    738733        sQuery = '';
    739         afDone = { 'TestSets': True, };
    740734        for iCrit, oCrit in enumerate(self.aCriteria):
    741735            if    oCrit.sState == FilterCriterion.ksState_Selected \
     
    14551449            """ Does the tedious result fetching and handling of missing bits. """
    14561450            dLeft = { oValue: 1 for oValue in oCrit.aoSelected };
     1451            oCrit.aoPossible = [];
    14571452            for aoRow in self._oDb.fetchAll():
    14581453                oCrit.aoPossible.append(FilterCriterionValueAndDescription(aoRow[0], aoRow[1]));
     
    14711466                                                                                       getattr(oMissing, sNameAttr),
    14721467                                                                                       fIrrelevant = True));
     1468
     1469        # Statuses.
     1470        oCrit = oFilter.aCriteria[TestResultFilter.kiTestStatus];
     1471        self._oDb.execute('SELECT TestSets.enmStatus, TestSets.enmStatus, COUNT(TestSets.idTestSet)\n'
     1472                          'FROM   TestSets\n' + oFilter.getTableJoins(iOmit = TestResultFilter.kiTestStatus) +
     1473                          'WHERE  ' + self._getTimePeriodQueryPart(tsNow, sPeriod) +
     1474                          oFilter.getWhereConditions(iOmit = TestResultFilter.kiTestStatus) +
     1475                          'GROUP BY TestSets.enmStatus\n'
     1476                          'ORDER BY TestSets.enmStatus\n');
     1477        workerDoFetch(None, fIdIsName = True);
    14731478
    14741479        # Scheduling groups (see getSchedGroups).
     
    15991604                          '               ON BuildCategories.idBuildCategory = BuildCategoryIDs.idBuildCategory\n'
    16001605                          'ORDER BY BuildCategories.sBranch DESC\n' );
    1601         workerDoFetch(BuildCategoryLogic, fIdIsName = True);
     1606        workerDoFetch(None, fIdIsName = True);
    16021607
    16031608        # Failure reasons.
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py

    r65053 r65054  
    901901        return True;
    902902
    903     def _generateResultFilter(self, oFilter, oResultLogic, tsNow, sPeriod, enmResultsGroupingType, aoGroupMembers,
    904                               fOnlyFailures, fOnlyNeedingReason):
     903    def _generateResultFilter(self, oFilter, oResultLogic, tsNow, sPeriod, enmResultsGroupingType = None, aoGroupMembers = None,
     904                              fOnlyFailures = False, fOnlyNeedingReason = False):
    905905        """
    906906        Generates the result filter for the left hand side.
     
    927927                 u' <dl>\n';
    928928
    929         for iCrit, oCrit in enumerate(oFilter.aCriteria):
     929        for oCrit in oFilter.aCriteria:
    930930            if len(oCrit.aoPossible) > 0:
    931931                sClass = 'sf-collapsable' if oCrit.sState == oCrit.ksState_Selected else 'sf-expandable';
     
    11881188        return self.ksDispatchRcAllDone;
    11891189
    1190     def _actionGenericReport(self, oModelType, oReportType):
     1190    def _actionGenericReport(self, oModelType, oFilterType, oReportType):
    11911191        """
    11921192        Generic report action.
    11931193        oReportType is a child of WuiReportContentBase.
     1194        oFilterType is a child of ModelFilterBase.
    11941195        oModelType is a child of ReportModelBase.
    11951196        """
     
    12071208            if aidSubjects is None:
    12081209                raise WuiException('Missing parameter %s' % (self.ksParamReportSubjectIds,));
     1210        oFilter = oFilterType().initFromParams(self);
    12091211        self._checkForUnknownParameters();
    12101212
     
    12171219            self.ksParamReportSubjectIds:       aidSubjects,
    12181220        };
    1219 
    1220         oModel   = oModelType(self._oDb, tsEffective, cPeriods, cHoursPerPeriod, sSubject, aidSubjects);
     1221        ## @todo oFilter.
     1222
     1223        oModel   = oModelType(self._oDb, tsEffective, cPeriods, cHoursPerPeriod, sSubject, aidSubjects, oFilter);
    12211224        oContent = oReportType(oModel, dParams, fSubReport = False, fnDPrint = self._oSrvGlue.dprint, oDisp = self);
    12221225        (self._sPageTitle, self._sPageBody) = oContent.show();
    12231226        sNavi = self._generateReportNavigation(tsEffective, cHoursPerPeriod, cPeriods);
    12241227        self._sPageBody = sNavi + self._sPageBody;
     1228
     1229        self._sPageFilter = self._generateResultFilter(oFilter, oModel, tsEffective, '%s hours' % (cHoursPerPeriod * cPeriods,));
    12251230        return True;
    12261231
    12271232    def _actionReportSummary(self):
    12281233        """ Action wrapper. """
    1229         from testmanager.core.report                import ReportLazyModel;
     1234        from testmanager.core.report                import ReportLazyModel, ReportFilter;
    12301235        from testmanager.webui.wuireport            import WuiReportSummary;
    1231         return self._actionGenericReport(ReportLazyModel, WuiReportSummary);
     1236        return self._actionGenericReport(ReportLazyModel, ReportFilter, WuiReportSummary);
    12321237
    12331238    def _actionReportRate(self):
    12341239        """ Action wrapper. """
    1235         from testmanager.core.report                import ReportLazyModel;
     1240        from testmanager.core.report                import ReportLazyModel, ReportFilter;
    12361241        from testmanager.webui.wuireport            import WuiReportSuccessRate;
    1237         return self._actionGenericReport(ReportLazyModel, WuiReportSuccessRate);
     1242        return self._actionGenericReport(ReportLazyModel, ReportFilter, WuiReportSuccessRate);
    12381243
    12391244    def _actionReportTestCaseFailures(self):
    12401245        """ Action wrapper. """
    1241         from testmanager.core.report                import ReportLazyModel;
     1246        from testmanager.core.report                import ReportLazyModel, ReportFilter;
    12421247        from testmanager.webui.wuireport            import WuiReportTestCaseFailures;
    1243         return self._actionGenericReport(ReportLazyModel, WuiReportTestCaseFailures);
     1248        return self._actionGenericReport(ReportLazyModel, ReportFilter, WuiReportTestCaseFailures);
    12441249
    12451250    def _actionReportFailureReasons(self):
    12461251        """ Action wrapper. """
    1247         from testmanager.core.report                import ReportLazyModel;
     1252        from testmanager.core.report                import ReportLazyModel, ReportFilter;
    12481253        from testmanager.webui.wuireport            import WuiReportFailureReasons;
    1249         return self._actionGenericReport(ReportLazyModel, WuiReportFailureReasons);
     1254        return self._actionGenericReport(ReportLazyModel, ReportFilter, WuiReportFailureReasons);
    12501255
    12511256    def _actionGraphWiz(self):
Note: See TracChangeset for help on using the changeset viewer.

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