VirtualBox

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


Ignore:
Timestamp:
May 28, 2016 8:36:17 PM (9 years ago)
Author:
vboxsync
Message:

Quick 'inbox' implementation by extending the current test case failure listing with a filter on whether a reason has been assigned or not. Renamed it 'Sheriff', short for 'Testing Sheriff'.

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

Legend:

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

    r61258 r61267  
    445445    ksParam_sComment            = 'TestResultFailure_sComment';
    446446
    447     kasAllowNullAttributes      = ['tsEffective', 'tsExpire', 'uidAuthor', 'sComment' ];
     447    kasAllowNullAttributes      = ['tsEffective', 'tsExpire', 'uidAuthor', 'sComment', 'idTestSet' ];
    448448
    449449    kcDbColumns                 = 7;
     
    618618        self.oFailureReason          = None;
    619619        if aoRow[31] is not None:
    620             self.oFailureReason = oFailureReasonLogic.cachedLookup(aoRow[30]);
     620            self.oFailureReason = oFailureReasonLogic.cachedLookup(aoRow[31]);
    621621        self.oFailureReasonAssigner  = None;
    622622        if aoRow[32] is not None:
    623             self.oFailureReasonAssigner = oUserAccountLogic.cachedLookup(aoRow[31]);
     623            self.oFailureReasonAssigner = oUserAccountLogic.cachedLookup(aoRow[32]);
    624624        self.tsFailureReasonAssigned = aoRow[33];
    625625        self.sFailureReasonComment   = aoRow[34];
     
    769769    kdResultGroupingMap = {
    770770        ksResultsGroupingTypeNone: (
    771             # Grouping tables;     # Grouping field;          # Grouping where addition.  # Sort by overrides.
    772             'TestSets',            None,                      None,                       {}
     771            # Grouping tables;                # Grouping field;          # Grouping where addition.  # Sort by overrides.
     772            '',                                None,                      None,                       {}
    773773        ),
    774         ksResultsGroupingTypeTestGroup:  ('TestSets',   'TestSets.idTestGroup',     None, {}),
    775         ksResultsGroupingTypeTestBox:    ('TestSets',   'TestSets.idTestBox',       None, {}),
    776         ksResultsGroupingTypeTestCase:   ('TestSets',   'TestSets.idTestCase',      None, {}),
     774        ksResultsGroupingTypeTestGroup:  ('', 'TestSets.idTestGroup',     None,                {}),
     775        ksResultsGroupingTypeTestBox:    ('', 'TestSets.idTestBox',       None,                {}),
     776        ksResultsGroupingTypeTestCase:   ('', 'TestSets.idTestCase',      None,                {}),
    777777        ksResultsGroupingTypeBuildRev: (
    778             'TestSets, Builds',
     778            ', Builds',
    779779            'Builds.iRevision',
    780780            ' AND Builds.idBuild      = TestSets.idBuild'
     
    784784        ),
    785785        ksResultsGroupingTypeSchedGroup: (
    786             'TestSets, TestBoxes',
     786            ', TestBoxes',
    787787            'TestBoxes.idSchedGroup',
    788788            ' AND TestSets.idGenTestBox = TestBoxes.idGenTestBox',
     
    809809        self.oUserAccountLogic   = None;
    810810
    811     def _getTimePeriodQueryPart(self, tsNow, sInterval):
     811    def _getTimePeriodQueryPart(self, tsNow, sInterval, sExtraIndent = ''):
    812812        """
    813813        Get part of SQL query responsible for SELECT data within
     
    819819        if tsNow is None:
    820820            sRet =        '(TestSets.tsDone IS NULL OR TestSets.tsDone >= (CURRENT_TIMESTAMP - \'%s\'::interval))\n' \
    821                    '   AND TestSets.tsCreated >= (CURRENT_TIMESTAMP  - \'%s\'::interval - \'%u months\'::interval)\n' \
    822                  % (sInterval, sInterval, cMonthsMourningPeriod);
     821                   '%s   AND TestSets.tsCreated >= (CURRENT_TIMESTAMP  - \'%s\'::interval - \'%u months\'::interval)\n' \
     822                 % ( sInterval,
     823                     sExtraIndent, sInterval, cMonthsMourningPeriod);
    823824        else:
    824825            sTsNow = '\'%s\'::TIMESTAMP' % (tsNow,); # It's actually a string already. duh.
    825826            sRet =        'TestSets.tsCreated <= %s\n' \
    826                    '   AND TestSets.tsCreated >= (%s  - \'%s\'::interval - \'%u months\'::interval)\n' \
    827                    '   AND (TestSets.tsDone IS NULL OR TestSets.tsDone >= (%s - \'%s\'::interval))\n' \
     827                   '%   AND TestSets.tsCreated >= (%s  - \'%s\'::interval - \'%u months\'::interval)\n' \
     828                   '%   AND (TestSets.tsDone IS NULL OR TestSets.tsDone >= (%s - \'%s\'::interval))\n' \
    828829                 % ( sTsNow,
    829                      sTsNow, sInterval, cMonthsMourningPeriod,
    830                      sTsNow, sInterval );
     830                     sExtraIndent, sTsNow, sInterval, cMonthsMourningPeriod,
     831                     sExtraIndent, sTsNow, sInterval );
    831832        return sRet
    832833
    833     def fetchResultsForListing(self, iStart, cMaxRows, tsNow, sInterval, enmResultSortBy,
    834                                enmResultsGroupingType, iResultsGroupingValue, fOnlyFailures):
     834    def fetchResultsForListing(self, iStart, cMaxRows, tsNow, sInterval, enmResultSortBy, # pylint: disable=R0913
     835                               enmResultsGroupingType, iResultsGroupingValue, fOnlyFailures, fOnlyNeedingReason):
    835836        """
    836837        Fetches TestResults table content.
     
    902903                  '       Builds,\n' \
    903904                  '       TestBoxes,\n' \
    904                   '       TestResults LEFT OUTER JOIN TestResultFailures\n' \
    905                   '            ON TestResults.idTestResult    = TestResultFailures.idTestResult\n' \
    906                   '           AND TestResultFailures.tsExpire = \'infinity\'::TIMESTAMP';
     905                  '       TestResults\n' \
     906                  '       LEFT OUTER JOIN TestResultFailures\n' \
     907                  '                    ON     TestResults.idTestResult    = TestResultFailures.idTestResult\n' \
     908                  '                       AND TestResultFailures.tsExpire = \'infinity\'::TIMESTAMP';
    907909        if sSortingOrderBy is not None and sSortingOrderBy.find('FailureReason') >= 0:
    908910            sQuery += '\n' \
    909911                      '       LEFT OUTER JOIN FailureReasons\n' \
    910                       '            ON TestResultFailures.idFailureReason = FailureReasons.idFailureReason\n' \
    911                       '           AND FailureReasons.tsExpire            = \'infinity\'::TIMESTAMP';
     912                      '                    ON    TestResultFailures.idFailureReason = FailureReasons.idFailureReason\n' \
     913                      '                       AND FailureReasons.tsExpire            = \'infinity\'::TIMESTAMP';
    912914        sQuery += ',\n'\
    913915                  '       TestCases,\n' \
     
    922924                  '                 TestSets.idGenTestCase AS idGenTestCase,\n' \
    923925                  '                 TestSets.idGenTestCaseArgs AS idGenTestCaseArgs\n' \
    924                   '          FROM  ' + sGroupingTables + sSortingTables + '\n' \
    925                   '          WHERE ' + self._getTimePeriodQueryPart(tsNow, sInterval);
    926         if fOnlyFailures:
    927             sQuery += '            AND TestSets.enmStatus != \'success\'::TestStatus_T' \
    928                       '            AND TestSets.enmStatus != \'running\'::TestStatus_T';
     926                  '          FROM  TestSets';
     927        if fOnlyNeedingReason:
     928            sQuery += '\n' \
     929                      '          LEFT OUTER JOIN TestResultFailures\n' \
     930                      '                       ON     TestSets.idTestSet          = TestResultFailures.idTestSet\n' \
     931                      '                          AND TestResultFailures.tsExpire = \'infinity\'::TIMESTAMP';
     932        sQuery += sGroupingTables.replace(',', ',\n                ');
     933        sQuery += sSortingTables.replace( ',', ',\n                ');
     934        sQuery += '\n' \
     935                  '          WHERE ' + self._getTimePeriodQueryPart(tsNow, sInterval, '         ');
     936        if fOnlyFailures or fOnlyNeedingReason:
     937            sQuery += '            AND TestSets.enmStatus != \'success\'::TestStatus_T\n' \
     938                      '            AND TestSets.enmStatus != \'running\'::TestStatus_T\n';
     939        if fOnlyNeedingReason:
     940            sQuery += '            AND TestResultFailures.idTestSet IS NULL\n';
    929941        if sGroupingField is not None:
    930942            sQuery += '            AND %s = %d\n' % (sGroupingField, iResultsGroupingValue,);
     
    972984        return aoRows
    973985
    974     def getEntriesCount(self, tsNow, sInterval, enmResultsGroupingType, iResultsGroupingValue, fOnlyFailures):
     986    def getEntriesCount(self, tsNow, sInterval, enmResultsGroupingType, iResultsGroupingValue, fOnlyFailures, fOnlyNeedingReason):
    975987        """
    976988        Get number of table records.
     
    9971009        # Construct the query.
    9981010        #
    999         sQuery = 'SELECT COUNT(idTestSet)\n' \
    1000                  'FROM   ' + sGroupingTables + '\n' \
    1001                  'WHERE  ' + self._getTimePeriodQueryPart(tsNow, sInterval);
    1002         if fOnlyFailures:
    1003             sQuery += '   AND TestSets.enmStatus != \'success\'::TestStatus_T' \
    1004                       '   AND TestSets.enmStatus != \'running\'::TestStatus_T';
     1011        sQuery = 'SELECT COUNT(TestSets.idTestSet)\n' \
     1012                 'FROM   TestSets';
     1013        if fOnlyNeedingReason:
     1014            sQuery += '\n' \
     1015                      '       LEFT OUTER JOIN TestResultFailures\n' \
     1016                      '                    ON     TestSets.idTestSet          = TestResultFailures.idTestSet\n' \
     1017                      '                       AND TestResultFailures.tsExpire = \'infinity\'::TIMESTAMP';
     1018        sQuery += sGroupingTables.replace(',', ',\n       ');
     1019        sQuery += '\n' \
     1020                  'WHERE  ' + self._getTimePeriodQueryPart(tsNow, sInterval);
     1021        if fOnlyFailures or fOnlyNeedingReason:
     1022            sQuery += '   AND TestSets.enmStatus != \'success\'::TestStatus_T\n' \
     1023                      '   AND TestSets.enmStatus != \'running\'::TestStatus_T\n';
     1024        if fOnlyNeedingReason:
     1025            sQuery += '   AND TestResultFailures.idTestSet IS NULL\n';
    10051026        if sGroupingField is not None:
    10061027            sQuery += '   AND %s = %d\n' % (sGroupingField, iResultsGroupingValue,);
     
    10621083        """
    10631084
    1064         ## @todo do all in one query.
    1065         self._oDb.execute('SELECT DISTINCT TestBoxes.idTestBox, TestBoxes.idGenTestBox\n'
    1066                           'FROM TestBoxes, TestSets\n'
    1067                           'WHERE TestSets.idGenTestBox = TestBoxes.idGenTestBox\n'
    1068                           '  AND ' + self._getTimePeriodQueryPart(tsNow, sPeriod) +
    1069                           'ORDER BY TestBoxes.idTestBox, TestBoxes.idGenTestBox DESC' );
    1070         idPrevTestBox = -1;
    1071         asIdGenTestBoxes = [];
     1085        self._oDb.execute('SELECT TestBoxes.*\n'
     1086                          'FROM   TestBoxes,\n'
     1087                          '       ( SELECT TestBoxes.idTestBox  AS idTestBox,\n'
     1088                          '         MAX(TestBoxes.idGenTestBox) AS idGenTestBox\n'
     1089                          '         FROM   TestBoxes, TestSets\n'
     1090                          '         WHERE  TestSets.idGenTestBox = TestBoxes.idGenTestBox\n'
     1091                          '           AND ' + self._getTimePeriodQueryPart(tsNow, sPeriod, '        ') +
     1092                          '         GROUP BY TestBoxes.idTestBox\n'
     1093                          '         ORDER BY TestBoxes.idTestBox\n'
     1094                          '       ) AS TestBoxIDs\n'
     1095                          'WHERE  TestBoxes.idGenTestBox = TestBoxIDs.idGenTestBox\n'
     1096                          'ORDER BY TestBoxes.sName\n' );
     1097        aoRet = []
    10721098        for aoRow in self._oDb.fetchAll():
    1073             if aoRow[0] != idPrevTestBox:
    1074                 idPrevTestBox = aoRow[0];
    1075                 asIdGenTestBoxes.append(str(aoRow[1]));
    1076 
    1077         aoRet = []
    1078         if len(asIdGenTestBoxes) > 0:
    1079             self._oDb.execute('SELECT *\n'
    1080                               'FROM TestBoxes\n'
    1081                               'WHERE idGenTestBox IN (' + ','.join(asIdGenTestBoxes) + ')\n'
    1082                               'ORDER BY sName');
    1083             for aoRow in self._oDb.fetchAll():
    1084                 aoRet.append(TestBoxData().initFromDbRow(aoRow));
     1099            aoRet.append(TestBoxData().initFromDbRow(aoRow));
    10851100        return aoRet
    10861101
     
    21822197    def _resolveSetTestIdIfMissing(self, oData):
    21832198        """ Resolve any missing idTestSet reference (it's a duplicate for speed efficiency). """
    2184         if oData.idTestSet is None and oData.idTestResult is not None :
     2199        if oData.idTestSet is None and oData.idTestResult is not None:
    21852200            self._oDb.execute('SELECT idTestSet FROM TestResults WHERE idTestResult = %s', (oData.idTestResult,));
    2186             oData.idTestResult = self._oDb.fetchOne()[0];
     2201            oData.idTestSet = self._oDb.fetchOne()[0];
    21872202        return oData;
    21882203
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuibase.py

    r61250 r61267  
    919919
    920920
    921     def _actionGenericFormPost(self, sMode, fnLogicAction, oDataType, oFormType, sRedirectTo, fStrict=True):
     921    def _actionGenericFormPost(self, sMode, fnLogicAction, oDataType, oFormType, sRedirectTo, fStrict = True):
    922922        """
    923923        Generic POST request handling from a WuiFormContentBase child.
     
    989989        return self._actionGenericFormPost(WuiFormContentBase.ksMode_Add, oLogic.addEntry, oDataType, oFormType,
    990990                                           '?' + webutils.encodeUrlParams({self.ksParamAction: sRedirAction}), fStrict=fStrict)
     991
    991992    def _actionGenericFormEditPost(self, oDataType, oLogicType, oFormType, sRedirAction, fStrict = True):
    992993        """
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py

    r61250 r61267  
    154154    ksParamGroupMemberId        = 'GroupMemberId'
    155155    ## Optional parameter for indicating whether to restrict the listing to failures only.
    156     ksParamOnlyFailures         = 'OnlyFailures'
     156    ksParamOnlyFailures         = 'OnlyFailures';
     157    ## The sheriff parameter for getting failures needing a reason or two assigned to them.
     158    ksParamOnlyNeedingReason    = 'OnlyNeedingReason';
    157159    ## Result listing sorting.
    158160    ksParamTestResultsSortBy    = 'enmSortBy'
     
    271273
    272274        # Shorthand to keep within margins.
    273         sActUrlBase = self._sActionUrlBase;
    274         sOFail = '&%s' % webutils.encodeUrlParams({self.ksParamOnlyFailures: True});
     275        sActUrlBase   = self._sActionUrlBase;
     276        sOnlyFailures = '&%s%s' % ( webutils.encodeUrlParams({self.ksParamOnlyFailures: True}), sExtraTimeNav, );
     277        sSheriff      = '&%s%s' % ( webutils.encodeUrlParams({self.ksParamOnlyNeedingReason: True}), sExtraTimeNav, );
    275278
    276279        self._aaoMenus = \
    277280        [
    278281            [
    279                 'Inbox',            sActUrlBase + 'TODO', ## @todo list of failures that needs categorizing.
    280                 []
     282                'Sheriff',     sActUrlBase + self.ksActionResultsUnGrouped + sSheriff,
     283                [
     284                    [ 'Ungrouped results',           sActUrlBase + self.ksActionResultsUnGrouped           + sSheriff ],
     285                    [ 'Grouped by Scheduling Group', sActUrlBase + self.ksActionResultsGroupedBySchedGroup + sSheriff ],
     286                    [ 'Grouped by Test Group',       sActUrlBase + self.ksActionResultsGroupedByTestGroup  + sSheriff ],
     287                    [ 'Grouped by TestBox',          sActUrlBase + self.ksActionResultsGroupedByTestBox    + sSheriff ],
     288                    [ 'Grouped by Test Case',        sActUrlBase + self.ksActionResultsGroupedByTestCase   + sSheriff ],
     289                    [ 'Grouped by Revision',         sActUrlBase + self.ksActionResultsGroupedByBuildRev   + sSheriff ],
     290                ]
    281291            ],
    282292            [
     
    300310            ],
    301311            [
    302                 'Test Failures',     sActUrlBase + self.ksActionResultsUnGrouped + sOFail + sExtraTimeNav,
     312                'Test Failures',     sActUrlBase + self.ksActionResultsUnGrouped + sOnlyFailures,
    303313                [
    304                     [ 'Ungrouped results',           sActUrlBase + self.ksActionResultsUnGrouped          +sOFail+sExtraTimeNav],
    305                     [ 'Grouped by Scheduling Group', sActUrlBase + self.ksActionResultsGroupedBySchedGroup+sOFail+sExtraTimeNav],
    306                     [ 'Grouped by Test Group',       sActUrlBase + self.ksActionResultsGroupedByTestGroup +sOFail+sExtraTimeNav],
    307                     [ 'Grouped by TestBox',          sActUrlBase + self.ksActionResultsGroupedByTestBox   +sOFail+sExtraTimeNav],
    308                     [ 'Grouped by Test Case',        sActUrlBase + self.ksActionResultsGroupedByTestCase  +sOFail+sExtraTimeNav],
    309                     [ 'Grouped by Revision',         sActUrlBase + self.ksActionResultsGroupedByBuildRev  +sOFail+sExtraTimeNav],
     314                    [ 'Ungrouped results',           sActUrlBase + self.ksActionResultsUnGrouped           + sOnlyFailures ],
     315                    [ 'Grouped by Scheduling Group', sActUrlBase + self.ksActionResultsGroupedBySchedGroup + sOnlyFailures ],
     316                    [ 'Grouped by Test Group',       sActUrlBase + self.ksActionResultsGroupedByTestGroup  + sOnlyFailures ],
     317                    [ 'Grouped by TestBox',          sActUrlBase + self.ksActionResultsGroupedByTestBox    + sOnlyFailures ],
     318                    [ 'Grouped by Test Case',        sActUrlBase + self.ksActionResultsGroupedByTestCase   + sOnlyFailures ],
     319                    [ 'Grouped by Revision',         sActUrlBase + self.ksActionResultsGroupedByBuildRev   + sOnlyFailures ],
    310320                ]
    311321            ],
     
    326336    def _isMenuMatch(self, sMenuUrl, sActionParam):
    327337        if super(WuiMain, self)._isMenuMatch(sMenuUrl, sActionParam):
     338            fOnlyNeedingReason = self.getBoolParam(self.ksParamOnlyNeedingReason, fDefault = False);
     339            if fOnlyNeedingReason:
     340                return (sMenuUrl.find(self.ksParamOnlyNeedingReason) > 0);
    328341            fOnlyFailures = self.getBoolParam(self.ksParamOnlyFailures, fDefault = False);
    329             return (sMenuUrl.find(self.ksParamOnlyFailures) > 0) == fOnlyFailures;
     342            return (sMenuUrl.find(self.ksParamOnlyFailures) > 0) == fOnlyFailures \
     343                and sMenuUrl.find(self.ksParamOnlyNeedingReason) < 0;
    330344        return False;
    331345
     
    705719        oListContentType is a child of WuiListContentBase.
    706720        """
    707         cItemsPerPage     = self.getIntParam(self.ksParamItemsPerPage,  iMin =  2, iMax =   9999, iDefault = 128);
    708         iPage             = self.getIntParam(self.ksParamPageNo,        iMin =  0, iMax = 999999, iDefault = 0);
    709         tsEffective       = self.getEffectiveDateParam();
    710         iGroupMemberId    = self.getIntParam(self.ksParamGroupMemberId, iMin = -1, iMax = 999999, iDefault = -1);
    711         fOnlyFailures     = self.getBoolParam(self.ksParamOnlyFailures, fDefault = False);
    712         enmResultSortBy   = self.getStringParam(self.ksParamTestResultsSortBy,
    713                                                 asValidValues = TestResultLogic.kasResultsSortBy,
    714                                                 sDefault = TestResultLogic.ksResultsSortByRunningAndStart);
     721        cItemsPerPage       = self.getIntParam(self.ksParamItemsPerPage,  iMin =  2, iMax =   9999, iDefault = 128);
     722        iPage               = self.getIntParam(self.ksParamPageNo,        iMin =  0, iMax = 999999, iDefault = 0);
     723        tsEffective         = self.getEffectiveDateParam();
     724        iGroupMemberId      = self.getIntParam(self.ksParamGroupMemberId, iMin = -1, iMax = 999999, iDefault = -1);
     725        fOnlyFailures       = self.getBoolParam(self.ksParamOnlyFailures, fDefault = False);
     726        fOnlyNeedingReason  = self.getBoolParam(self.ksParamOnlyNeedingReason, fDefault = False);
     727        enmResultSortBy     = self.getStringParam(self.ksParamTestResultsSortBy,
     728                                                  asValidValues = TestResultLogic.kasResultsSortBy,
     729                                                  sDefault = TestResultLogic.ksResultsSortByRunningAndStart);
    715730
    716731        # Get testing results period and validate it
    717         asValidValues     = [x for (x, _, _) in self.kaoResultPeriods]
    718         sCurPeriod        = self.getStringParam(self.ksParamEffectivePeriod, asValidValues = asValidValues,
    719                                                 sDefault = self.ksResultPeriodDefault)
     732        asValidValues       = [x for (x, _, _) in self.kaoResultPeriods]
     733        sCurPeriod          = self.getStringParam(self.ksParamEffectivePeriod, asValidValues = asValidValues,
     734                                                  sDefault = self.ksResultPeriodDefault)
    720735        assert sCurPeriod != ''; # Impossible!
    721736
     
    790805                                                    enmResultsGroupingType = enmResultsGroupingType,
    791806                                                    iResultsGroupingValue = idMember,
    792                                                     fOnlyFailures = fOnlyFailures);
     807                                                    fOnlyFailures = fOnlyFailures,
     808                                                    fOnlyNeedingReason = fOnlyNeedingReason);
    793809            if cEntries == 0: # Do not display empty groups
    794810                continue
     
    800816                                                            enmResultsGroupingType = enmResultsGroupingType,
    801817                                                            iResultsGroupingValue = idMember,
    802                                                             fOnlyFailures = fOnlyFailures);
     818                                                            fOnlyFailures = fOnlyFailures,
     819                                                            fOnlyNeedingReason = fOnlyNeedingReason);
    803820            cEntriesMax = max(cEntriesMax, cEntries)
    804821
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuitestresult.py

    r61263 r61267  
    394394                oForm.addTextHidden(TestResultFailureData.ksParam_uidAuthor, oData.uidAuthor);
    395395                oForm.addSubmit('Change Reason');
    396 
    397396            else:
    398397                oForm.addComboBox(TestResultFailureData.ksParam_idFailureReason, -1, 'Reason', aoFailureReasons,
     
    808807        # Reason:
    809808        oReason = None;
     809        #assert (oEntry.oFailureReason is None) == (oEntry.tsFailureReasonAssigned is None);
    810810        if oEntry.oFailureReason is not None:
    811811            sReasonTitle  = 'Reason:  \t%s\n' % ( oEntry.oFailureReason.sShort, );
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