Changeset 65091 in vbox
- Timestamp:
- Jan 4, 2017 2:04:12 AM (8 years ago)
- Location:
- trunk/src/VBox/ValidationKit/testmanager
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/testmanager/core/base.py
r65080 r65091 1164 1164 self.sHover = sHover; ##< Optional hover/title string. 1165 1165 self.fIrrelevant = fIrrelevant; ##< Irrelevant filter option, only present because it's selected 1166 self.aoSubs = []; ##< References to FilterCriterion.oSub.aoPossible. 1166 1167 1167 1168 … … 1190 1191 1191 1192 def __init__(self, sName, sVarNm = None, sType = ksType_UInt, sState = ksState_NotSelected, sKind = ksKind_AnyOf, 1192 sTable = None, sColumn = None ):1193 sTable = None, sColumn = None, oSub = None): 1193 1194 assert len(sVarNm) in (2,3); # required by wuimain.py 1194 1195 self.sName = sName; … … 1197 1198 self.sType = sType; 1198 1199 self.sKind = sKind; 1199 self.aoSelected = []; #Single value, any type.1200 self.aoPossible = []; #type: list[FilterCriterionValueAndDescription]1200 self.aoSelected = []; ##< Single value, any type. 1201 self.aoPossible = []; ##< type: list[FilterCriterionValueAndDescription] 1201 1202 self.sTable = sTable; 1202 1203 self.sColumn = sColumn; 1203 self.fExpanded = None; ##< Tristate (None, False, True) indicating whether the criterion should be shown/hid regardless. 1204 self.fExpanded = None; ##< Tristate (None, False, True) 1205 self.oSub = oSub; ##< type: FilterCriterion 1204 1206 1205 1207 … … 1232 1234 self.aCriteria = []; # type: list[FilterCriterion] 1233 1235 1236 def _initFromParamsWorker(self, oDisp, oCriterion): 1237 """ Worker for initFromParams. """ 1238 if oCriterion.sType == FilterCriterion.ksType_UInt: 1239 oCriterion.aoSelected = oDisp.getListOfIntParams(oCriterion.sVarNm, iMin = 0, aiDefaults = []); 1240 elif oCriterion.sType == FilterCriterion.ksType_String: 1241 oCriterion.aoSelected = oDisp.getListOfStrParams(oCriterion.sVarNm, asDefaults = []); 1242 if len(oCriterion.aoSelected) > 100: 1243 raise TMExceptionBase('Variable %s has %u value, max allowed is 100!' 1244 % (oCriterion.sVarNm, len(oCriterion.aoSelected))); 1245 for sValue in oCriterion.aoSelected: 1246 if len(sValue) > 64 \ 1247 or '\'' in sValue \ 1248 or sValue[-1] == '\\': 1249 raise TMExceptionBase('Variable %s has an illegal value "%s"!' % (oCriterion.sVarNm, sValue)); 1250 else: 1251 assert False; 1252 if len(oCriterion.aoSelected) > 0: 1253 oCriterion.sState = FilterCriterion.ksState_Selected; 1254 else: 1255 oCriterion.sState = FilterCriterion.ksState_NotSelected; 1256 1257 if oCriterion.oSub is not None: 1258 self._initFromParamsWorker(oDisp, oCriterion.oSub); 1259 return; 1260 1234 1261 def initFromParams(self, oDisp): # type: (WuiDispatcherBase) -> self 1235 1262 """ … … 1240 1267 1241 1268 for oCriterion in self.aCriteria: 1242 if oCriterion.sType == FilterCriterion.ksType_UInt: 1243 oCriterion.aoSelected = oDisp.getListOfIntParams(oCriterion.sVarNm, iMin = 0, aiDefaults = []); 1244 elif oCriterion.sType == FilterCriterion.ksType_String: 1245 oCriterion.aoSelected = oDisp.getListOfStrParams(oCriterion.sVarNm, asDefaults = []); 1246 if len(oCriterion.aoSelected) > 100: 1247 raise TMExceptionBase('Variable %s has %u value, max allowed is 100!' 1248 % (oCriterion.sVarNm, len(oCriterion.aoSelected))); 1249 for sValue in oCriterion.aoSelected: 1250 if len(sValue) > 64 \ 1251 or '\'' in sValue \ 1252 or sValue[-1] == '\\': 1253 raise TMExceptionBase('Variable %s has an illegal value "%s"!' % (oCriterion.sVarNm, sValue)); 1254 else: 1255 assert False; 1256 if len(oCriterion.aoSelected) > 0: 1257 oCriterion.sState = FilterCriterion.ksState_Selected; 1258 else: 1259 oCriterion.sState = FilterCriterion.ksState_NotSelected; 1269 self._initFromParamsWorker(oDisp, oCriterion); 1260 1270 return self; 1261 1271 -
trunk/src/VBox/ValidationKit/testmanager/core/testresults.py
r65084 r65091 660 660 kiMisc = 12; 661 661 kiOses = 13; 662 kiOsVersions = 14; 663 kiPythonVersions = 15; 664 kiFailReasons = 16; 662 kiPythonVersions = 14; 663 kiFailReasons = 15; 665 664 666 665 kiMisc_NestedPaging = 0; … … 743 742 assert self.aCriteria[self.kiMisc] is oCrit; 744 743 745 oCrit = FilterCriterion('OSes', sVarNm = 'os', sTable = 'TestBoxesWithStrings', sColumn = 'idStrOs'); 744 oCrit = FilterCriterion('OS / Version', sVarNm = 'os', sTable = 'TestBoxesWithStrings', sColumn = 'idStrOs', 745 oSub = FilterCriterion('OS Versions', sVarNm = 'ov', 746 sTable = 'TestBoxesWithStrings', sColumn = 'idStrOsVersion')); 746 747 self.aCriteria.append(oCrit); 747 748 assert self.aCriteria[self.kiOses] is oCrit; 748 749 oCrit = FilterCriterion('OS Versions', sVarNm = 'ov', sTable = 'TestBoxesWithStrings', sColumn = 'idStrOsVersion');750 self.aCriteria.append(oCrit);751 assert self.aCriteria[self.kiOsVersions] is oCrit;752 749 753 750 oCrit = FilterCriterion('Python', sVarNm = 'py', sTable = 'TestBoxesWithStrings', sColumn = 'iPythonHexVersion'); … … 772 769 }; 773 770 771 def _getWhereWorker(self, iCrit, oCrit, sExtraIndent, iOmit): 772 """ Formats one - main or sub. """ 773 sQuery = ''; 774 if oCrit.sState == FilterCriterion.ksState_Selected and iCrit != iOmit: 775 if iCrit == self.kiMisc: 776 for iValue in oCrit.aoSelected: 777 if iValue in self.kdMiscConditions: 778 sQuery += '%s AND %s\n' % (sExtraIndent, self.kdMiscConditions[iValue],); 779 else: 780 if iCrit == self.kiMemory: 781 sQuery += '%s AND (%s.%s / 1024) IN (' % (sExtraIndent, oCrit.sTable, oCrit.sColumn,); 782 else: 783 sQuery += '%s AND %s.%s IN (' % (sExtraIndent, oCrit.sTable, oCrit.sColumn,); 784 if oCrit.sType == FilterCriterion.ksType_String: 785 sQuery += ', '.join('\'%s\'' % (sValue,) for sValue in oCrit.aoSelected) + ')\n'; 786 else: 787 sQuery += ', '.join(str(iValue) for iValue in oCrit.aoSelected) + ')\n'; 788 if oCrit.oSub is not None: 789 sQuery += self._getWhereWorker(iCrit | (((iCrit >> 8) + 1) << 8), oCrit.oSub, sExtraIndent, iOmit); 790 return sQuery; 791 774 792 def getWhereConditions(self, sExtraIndent = '', iOmit = -1): 775 793 """ … … 779 797 sQuery = ''; 780 798 for iCrit, oCrit in enumerate(self.aCriteria): 781 if oCrit.sState == FilterCriterion.ksState_Selected and iCrit != iOmit: 782 if iCrit == self.kiMisc: 783 for iValue in oCrit.aoSelected: 784 if iValue in self.kdMiscConditions: 785 sQuery += '%s AND %s\n' % (sExtraIndent, self.kdMiscConditions[iValue],); 786 else: 787 if iCrit == self.kiMemory: 788 sQuery += '%s AND (%s.%s / 1024) IN (' % (sExtraIndent, oCrit.sTable, oCrit.sColumn,); 789 else: 790 sQuery += '%s AND %s.%s IN (' % (sExtraIndent, oCrit.sTable, oCrit.sColumn,); 791 if oCrit.sType == FilterCriterion.ksType_String: 792 sQuery += ', '.join('\'%s\'' % (sValue,) for sValue in oCrit.aoSelected) + ')\n'; 793 else: 794 sQuery += ', '.join(str(iValue) for iValue in oCrit.aoSelected) + ')\n'; 799 sQuery += self._getWhereWorker(iCrit, oCrit, sExtraIndent, iOmit); 795 800 return sQuery; 796 801 … … 1554 1559 fIrrelevant = True)); 1555 1560 1561 def workerDoFetchNested(): 1562 """ Does the tedious result fetching and handling of missing bits. """ 1563 oCrit.aoPossible = []; 1564 oCrit.oSub.aoPossible = []; 1565 dLeft = { oValue: 1 for oValue in oCrit.aoSelected }; 1566 dSubLeft = { oValue: 1 for oValue in oCrit.oSub.aoSelected }; 1567 oMain = None; 1568 for aoRow in self._oDb.fetchAll(): 1569 if oMain is None or oMain.oValue != aoRow[0]: 1570 oMain = FilterCriterionValueAndDescription(aoRow[0], aoRow[1], 0); 1571 oCrit.aoPossible.append(oMain); 1572 if aoRow[0] in dLeft: 1573 del dLeft[aoRow[0]]; 1574 oCurSub = FilterCriterionValueAndDescription(aoRow[2], aoRow[3], aoRow[4]); 1575 oCrit.oSub.aoPossible.append(oCurSub); 1576 if aoRow[2] in dLeft: 1577 del dSubLeft[aoRow[2]]; 1578 1579 oMain.aoSubs.append(oCurSub); 1580 oMain.cTimes += aoRow[4]; 1581 1582 if len(dLeft) > 0: 1583 pass; ## @todo 1584 1556 1585 # Statuses. 1557 1586 oCrit = oFilter.aCriteria[TestResultFilter.kiTestStatus]; … … 1606 1635 workerDoFetch(TestBoxLogic); 1607 1636 1608 # Testbox OSes .1637 # Testbox OSes and versions. 1609 1638 oCrit = oFilter.aCriteria[TestResultFilter.kiOses]; 1610 1639 self._oDb.execute('SELECT TestBoxesWithStrings.idStrOs,\n' 1611 1640 ' TestBoxesWithStrings.sOs,\n' 1641 ' TestBoxesWithStrings.idStrOsVersion,\n' 1642 ' TestBoxesWithStrings.sOsVersion,\n' 1612 1643 ' SUM(TestBoxGenIDs.cTimes)\n' 1613 1644 'FROM ( SELECT TestSets.idGenTestBox,\n' … … 1622 1653 ' LEFT OUTER JOIN TestBoxesWithStrings\n' 1623 1654 ' ON TestBoxesWithStrings.idGenTestBox = TestBoxGenIDs.idGenTestBox\n' 1624 'GROUP BY TestBoxesWithStrings.idStrOs, TestBoxesWithStrings.sOs\n' 1625 'ORDER BY TestBoxesWithStrings.sOs\n' ); 1626 workerDoFetch(None, fIdIsName = True); 1627 1628 # Testbox OS versions . 1629 oCrit = oFilter.aCriteria[TestResultFilter.kiOsVersions]; 1630 self._oDb.execute('SELECT TestBoxesWithStrings.idStrOsVersion,\n' 1631 ' TestBoxesWithStrings.sOsVersion,\n' 1632 ' SUM(TestBoxGenIDs.cTimes)\n' 1633 'FROM ( SELECT TestSets.idGenTestBox AS idGenTestBox,\n' 1634 ' COUNT(TestSets.idTestSet) AS cTimes\n' 1635 ' FROM TestSets\n' + oFilter.getTableJoins(iOmit = TestResultFilter.kiOsVersions) + 1636 ''.join(' , %s\n' % (sTable,) for sTable in oReportModel.getExtraSubjectTables()) + 1637 ' WHERE ' + self._getTimePeriodQueryPart(tsNow, sPeriod, ' ') + 1638 oFilter.getWhereConditions(iOmit = TestResultFilter.kiOsVersions) + 1639 oReportModel.getExtraSubjectWhereExpr() + 1640 ' GROUP BY TestSets.idGenTestBox\n' 1641 ' ) AS TestBoxGenIDs\n' 1642 ' LEFT OUTER JOIN TestBoxesWithStrings\n' 1643 ' ON TestBoxesWithStrings.idGenTestBox = TestBoxGenIDs.idGenTestBox\n' 1644 'GROUP BY TestBoxesWithStrings.idStrOsVersion, TestBoxesWithStrings.sOsVersion\n' 1645 'ORDER BY TestBoxesWithStrings.sOsVersion\n' ); 1646 workerDoFetch(None, fIdIsName = True); 1655 'GROUP BY TestBoxesWithStrings.idStrOs,\n' 1656 ' TestBoxesWithStrings.sOs,\n' 1657 ' TestBoxesWithStrings.idStrOsVersion,\n' 1658 ' TestBoxesWithStrings.sOsVersion\n' 1659 'ORDER BY TestBoxesWithStrings.sOs,\n' 1660 ' TestBoxesWithStrings.sOsVersion\n' 1661 ); 1662 workerDoFetchNested(); 1647 1663 1648 1664 # Testbox CPU/OS architectures. … … 1770 1786 workerDoFetch(None, fIdIsName = True); 1771 1787 for oCur in oCrit.aoPossible: 1772 oCur.sDesc = TestBoxData.formatPythonVersionEx(oCur.oValue); 1788 oCur.sDesc = TestBoxData.formatPythonVersionEx(oCur.oValue); # pylint: disable=redefined-variable-type 1773 1789 1774 1790 # Testcases (see getTestCases). -
trunk/src/VBox/ValidationKit/testmanager/htdocs/css/common.css
r65090 r65091 324 324 } 325 325 326 327 326 /* Filters: */ 328 327 #side-filters p:first-child { … … 333 332 } 334 333 335 #side-filters dd.sf-collaps able {334 #side-filters dd.sf-collapsible { 336 335 display: block; 337 336 } … … 378 377 } 379 378 380 #side-filters ul {379 #side-filters dd > ul { 381 380 max-height: 22em; 382 381 overflow: auto; 382 } 383 384 #side-filters ul ul { 385 margin-left: 1.4em; 386 } 387 388 #side-filters li { 389 padding-top: 1px; 390 padding-bottom: 1px; 391 overflow-wrap: break-word; 392 } 393 394 ul.sf-checkbox-collapsible { 395 display: block; 396 } 397 398 ul.sf-checkbox-expandable { 399 display: none; 383 400 } 384 401 … … 407 424 margin-right: 3px; 408 425 margin-bottom: 0.5em; 426 font-family: Times New, Times, serif; 409 427 font-size: 0.86em; 428 font-style: normal; 429 font-weight: normal; 410 430 line-height: 1.2em; 411 font-style: normal;412 431 text-align: center; 413 432 } -
trunk/src/VBox/ValidationKit/testmanager/htdocs/js/common.js
r65085 r65091 353 353 354 354 355 /** @name Collaps able / Expandable items355 /** @name Collapsible / Expandable items 356 356 * @{ 357 357 */ … … 359 359 360 360 /** 361 * Toggles the collaps able / expandable state of a parent DD and DT unclke.361 * Toggles the collapsible / expandable state of a parent DD and DT uncle. 362 362 * 363 363 * @returns true 364 364 * @param oAnchor The anchor object. 365 365 */ 366 function toggleCollaps ableDtDd(oAnchor)366 function toggleCollapsibleDtDd(oAnchor) 367 367 { 368 368 var oParent = oAnchor.parentElement; … … 377 377 var sNewClass; 378 378 var sNewChar; 379 if ( sClass.substr(-11) == 'collaps able')379 if ( sClass.substr(-11) == 'collapsible') 380 380 { 381 381 sNewClass = sClass.substr(0, sClass.length - 11) + 'expandable'; … … 384 384 else if (sClass.substr(-10) == 'expandable') 385 385 { 386 sNewClass = sClass.substr(0, sClass.length - 10) + 'collaps able';386 sNewClass = sClass.substr(0, sClass.length - 10) + 'collapsible'; 387 387 sNewChar = '\u25BC'; /* black down-pointing triangle */ 388 388 } 389 389 else 390 390 { 391 console.log('toggleCollaps ableParent: Invalid class: ' + sClass);391 console.log('toggleCollapsibleParent: Invalid class: ' + sClass); 392 392 return true; 393 393 } … … 400 400 if (oDdElement) 401 401 oDdElement.className = sNewClass; 402 return true; 403 } 404 405 /** 406 * Shows/hides a sub-category UL according to checkbox status. 407 * 408 * The checkbox is expected to be within a label element or something. 409 * 410 * @returns true 411 * @param oInput The input checkbox. 412 */ 413 function toggleCollapsibleCheckbox(oInput) 414 { 415 var oParent = oInput.parentElement; 416 417 /* Find the UL sibling element. */ 418 var oUlElement = oParent.nextSibling; 419 while (oUlElement != null && oUlElement.tagName != 'UL') 420 oUlElement = oUlElement.nextSibling; 421 422 /* Change the visibility. */ 423 if (oInput.checked) 424 oUlElement.className = oUlElement.className.replace('expandable', 'collapsible'); 425 else 426 oUlElement.className = oUlElement.className.replace('collapsible', 'expandable'); 402 427 return true; 403 428 } -
trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py
r65090 r65091 933 933 for oCrit in oFilter.aCriteria: 934 934 if len(oCrit.aoPossible) > 0: 935 if oCrit.sState == oCrit.ksState_Selected \ 936 or len(oCrit.aoPossible) <= 2 \ 935 if ( oCrit.oSub is None \ 936 and ( oCrit.sState == oCrit.ksState_Selected \ 937 or len(oCrit.aoPossible) <= 2)) \ 938 or ( oCrit.oSub is not None \ 939 and ( oCrit.sState == oCrit.ksState_Selected \ 940 or oCrit.oSub.sState == oCrit.ksState_Selected \ 941 or (len(oCrit.aoPossible) <= 2 and len(oCrit.oSub.aoPossible) <= 2))) \ 937 942 or oCrit.fExpanded is True: 938 sClass = 'sf-collaps able';943 sClass = 'sf-collapsible'; 939 944 sChar = '▼'; 940 945 else: … … 942 947 sChar = '▶'; 943 948 944 sHtml += u' <dt class="%s"><a href="javascript:void(0)" onclick="toggleCollaps ableDtDd(this);">%s'\949 sHtml += u' <dt class="%s"><a href="javascript:void(0)" onclick="toggleCollapsibleDtDd(this);">%s'\ 945 950 u' %s</a></dt>\n' \ 946 951 u' <dd class="%s">\n' \ … … 950 955 for oDesc in oCrit.aoPossible: 951 956 fChecked = oDesc.oValue in oCrit.aoSelected; 952 sHtml += u' <li%s%s>< input type="checkbox" name="%s" value="%s"%s/>%s%s</li>\n' \957 sHtml += u' <li%s%s><label><input type="checkbox" name="%s" value="%s"%s%s/>%s%s</label>\n' \ 953 958 % ( ' class="side-filter-irrelevant"' if oDesc.fIrrelevant else '', 954 ' title="%s"' % (webutils.escapeAttr(oDesc.sHover,) if oDesc.sHover is not None else ''), 955 oCrit.sVarNm, oDesc.oValue, ' checked' if fChecked else '', 959 (' title="%s"' % (webutils.escapeAttr(oDesc.sHover,)) if oDesc.sHover is not None else ''), 960 oCrit.sVarNm, 961 oDesc.oValue, 962 ' checked' if fChecked else '', 963 ' onclick="toggleCollapsibleCheckbox(this);"' if oDesc.aoSubs is not None else '', 956 964 webutils.escapeElem(oDesc.sDesc), 957 965 '<span class="side-filter-count"> [%u]</span>' % (oDesc.cTimes) if oDesc.cTimes is not None 958 966 else '', ); 959 967 if oDesc.aoSubs is not None: 968 sHtml += u' <ul class="sf-checkbox-%s">\n' % ('collapsible' if fChecked else 'expandable', ); 969 for oSubDesc in oDesc.aoSubs: 970 fSubChecked = oSubDesc.oValue in oCrit.oSub.aoSelected; 971 sHtml += u' <li%s%s><label><input type="checkbox" name="%s" value="%s"%s/>%s%s</label>\n' \ 972 % ( ' class="side-filter-irrelevant"' if oSubDesc.fIrrelevant else '', 973 ' title="%s"' % ( webutils.escapeAttr(oSubDesc.sHover,) if oSubDesc.sHover is not None 974 else ''), 975 oCrit.oSub.sVarNm, oSubDesc.oValue, ' checked' if fSubChecked else '', 976 webutils.escapeElem(oSubDesc.sDesc), 977 '<span class="side-filter-count"> [%u]</span>' % (oSubDesc.cTimes) 978 if oSubDesc.cTimes is not None else '', ); 979 980 sHtml += u' </ul>\n'; 981 sHtml += u' </li>'; 960 982 sHtml += u' </ul>\n' \ 961 983 u' </dd>\n';
Note:
See TracChangeset
for help on using the changeset viewer.