Changeset 61271 in vbox for trunk/src/VBox/ValidationKit/testmanager/core
- Timestamp:
- May 29, 2016 2:45:57 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 107563
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/testmanager/core/report.py
r61270 r61271 221 221 222 222 223 223 224 class ReportHitRowBase(object): 224 225 """ A row in a period. """ 225 def __init__(self, cHits, tsMin = None, tsMax = None): 226 def __init__(self, idSubject, oSubject, cHits, tsMin = None, tsMax = None): 227 self.idSubject = idSubject; 228 self.oSubject = oSubject; 226 229 self.cHits = cHits; 227 230 self.tsMin = tsMin; 228 231 self.tsMax = tsMax; 229 232 233 class ReportHitRowWithTotalBase(ReportHitRowBase): 234 """ A row in a period. """ 235 def __init__(self, idSubject, oSubject, cHits, cTotal, tsMin = None, tsMax = None): 236 ReportHitRowBase.__init__(self, idSubject, oSubject, cHits, tsMin, tsMax) 237 self.cTotal = cTotal; 238 self.uPct = cHits * 100 / cTotal; 239 230 240 class ReportFailureReasonRow(ReportHitRowBase): 231 241 """ The account of one failure reason for a period. """ 232 242 def __init__(self, aoRow, oReason): 233 ReportHitRowBase.__init__(self, aoRow[ 1], aoRow[2], aoRow[3]);243 ReportHitRowBase.__init__(self, aoRow[0], oReason, aoRow[1], aoRow[2], aoRow[3]); 234 244 self.idFailureReason = aoRow[0]; 235 245 self.oReason = oReason; # FailureReasonDataEx 236 246 237 class ReportTestCaseFailureRow(ReportHitRow Base):247 class ReportTestCaseFailureRow(ReportHitRowWithTotalBase): 238 248 """ The account of one test case for a period. """ 239 def __init__(self, aoRow, aoTestCase): 240 ReportHitRowBase.__init__(self, aoRow[1], aoRow[2], aoRow[3]); 241 self.idTestCase = aoRow[0]; 242 self.aoTestCase = aoTestCase; # TestCaseDataEx 249 def __init__(self, aoRow, oTestCase): 250 ReportHitRowWithTotalBase.__init__(self, aoRow[0], oTestCase, aoRow[1], aoRow[4], aoRow[2], aoRow[3]); 243 251 244 252 … … 266 274 self.aoRows.append(oRow); 267 275 self.dRowsById[idRow] = oRow; 268 276 if idRow not in self.oSet.dSubjects: 277 self.oSet.dSubjects[idRow] = oData; 278 self._doStatsForRow(oRow, idRow, oData); 279 280 def _doStatsForRow(self, oRow, idRow, oData): 281 """ Does the statistics for a row. Helper for appendRow as well as helpRecalcStats. """ 269 282 if oRow.tsMin is not None and oRow.tsMin < self.tsMin: 270 283 self.tsMin = oRow.tsMin; … … 278 291 self.cMinHits = oRow.cHits; 279 292 280 if idRow in self.oSet.dc TotalsPerId:281 self.oSet.dc TotalsPerId[idRow] += oRow.cHits;293 if idRow in self.oSet.dcHitsPerId: 294 self.oSet.dcHitsPerId[idRow] += oRow.cHits; 282 295 else: 283 self.dFirst[idRow] = oData; 284 self.oSet.dSubjects[idRow] = oData; 285 self.oSet.dcTotalsPerId[idRow] = oRow.cHits; 286 self.oSet.diPeriodFirst[idRow] = self.iPeriod; 287 self.oSet.diPeriodLast[idRow] = self.iPeriod; 296 self.oSet.dcHitsPerId[idRow] = oRow.cHits; 297 298 if oRow.cHits > 0: 299 if idRow not in self.oSet.diPeriodFirst: 300 self.dFirst[idRow] = oData; 301 self.oSet.diPeriodFirst[idRow] = self.iPeriod; 302 self.oSet.diPeriodLast[idRow] = self.iPeriod; 303 304 def helperSetRecalcStats(self): 305 """ Recalc the statistics (do resetStats first on set). """ 306 for idRow, oRow in self.dRowsById.items(): 307 self._doStatsForRow(oRow, idRow, self.oSet.dSubjects[idRow]); 308 309 def helperSetResetStats(self): 310 """ Resets the statistics. """ 311 self.tsMin = self.tsEnd; 312 self.tsMax = self.tsStart; 313 self.cHits = 0; 314 self.cMaxHits = 0; 315 self.cMinHits = 99999999; 316 self.dFirst = {}; 317 self.dLast = {}; 318 319 def helperSetDeleteKeyFromSet(self, idKey): 320 """ Helper for ReportPeriodSetBase::deleteKey """ 321 if idKey in self.dRowsById: 322 oRow = self.dRowsById[idKey]; 323 self.aoRows.remove(oRow); 324 del self.dRowsById[idKey] 325 self.cHits -= oRow.cHits; 326 if idKey in self.dFirst: 327 del self.dFirst[idKey]; 328 if idKey in self.dLast: 329 del self.dLast[idKey]; 330 331 class ReportPeriodWithTotalBase(ReportPeriodBase): 332 """ In addition to the cHits, we also have a total to relate it too. """ 333 def __init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo): 334 ReportPeriodBase.__init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo); 335 self.cTotal = 0; 336 self.cMinTotal = 0; 337 self.cMaxTotal = 99999999; 338 339 def _doStatsForRow(self, oRow, idRow, oData): 340 assert isinstance(oRow, ReportHitRowWithTotalBase); 341 super(ReportPeriodWithTotalBase, self)._doStatsForRow(oRow, idRow, oData); 342 self.cTotal += oRow.cTotal; 343 if oRow.cTotal > self.cMaxTotal: 344 self.cMaxTotal = oRow.cTotal; 345 if oRow.cTotal < self.cMinTotal: 346 self.cMinTotal = oRow.cTotal; 347 if idRow in self.oSet.dcTotalPerId: 348 self.oSet.dcTotalPerId[idRow] += oRow.cTotal; 349 else: 350 self.oSet.dcTotalPerId[idRow] = oRow.cTotal; 351 352 def helperSetResetStats(self): 353 super(ReportPeriodWithTotalBase, self).helperSetResetStats(); 354 self.cTotal = 0; 355 self.cMinTotal = 0; 356 self.cMaxTotal = 99999999; 288 357 289 358 class ReportFailureReasonPeriod(ReportPeriodBase): … … 293 362 self.cWithoutReason = 0; # Number of failed test sets without any assigned reason. 294 363 295 class ReportTestCaseFailurePeriod(ReportPeriod Base):364 class ReportTestCaseFailurePeriod(ReportPeriodWithTotalBase): 296 365 """ A period in ReportTestCaseFailureSet. """ 297 366 def __init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo): 298 ReportPeriodBase.__init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo); 367 ReportPeriodWithTotalBase.__init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo); 368 299 369 300 370 … … 304 374 self.sIdAttr = sIdAttr; # The name of the key attribute. Mainly for documentation purposes. 305 375 self.aoPeriods = []; # Periods (ReportPeriodBase descendant) in ascending order (time wise). 306 self.dcTotalsPerId = {}; # Totals per subject ID (key).307 376 self.dSubjects = {}; # The subject data objects, keyed by the subject ID. 308 self.cHits = 0; # Total number of hits in all periods and all reasons. 377 self.dcHitsPerId = {}; # Sum hits per subject ID (key). 378 self.cHits = 0; # Sum number of hits in all periods and all reasons. 309 379 self.cMaxHits = 0; # Max hits in a row. 310 380 self.cMinHits = 0; # Min hits in a row. … … 322 392 assert isinstance(oPeriod, ReportPeriodBase); 323 393 self.aoPeriods.append(oPeriod); 324 394 self._doStatsForPeriod(oPeriod); 395 396 def _doStatsForPeriod(self, oPeriod): 397 """ Worker for appendPeriod and recalcStats. """ 325 398 self.cHits += oPeriod.cHits; 326 399 if oPeriod.cHits > self.cMaxHits: … … 333 406 if len(oPeriod.aoRows) < self.cMinHits: 334 407 self.cMinHits = len(oPeriod.aoRows); 408 409 def recalcStats(self): 410 """ Recalculates the statistics. ASSUMES finalizePass1 hasn't been done yet. """ 411 self.cHits = 0; 412 self.cMaxHits = 0; 413 self.cMinHits = 0; 414 self.cMaxRows = 0; 415 self.cMinRows = 0; 416 self.diPeriodFirst = {}; 417 self.diPeriodLast = {}; 418 self.dcHitsPerId = {}; 419 for oPeriod in self.aoPeriods: 420 oPeriod.helperSetResetStats(); 421 422 for oPeriod in self.aoPeriods: 423 oPeriod.helperSetRecalcStats(); 424 self._doStatsForPeriod(oPeriod); 425 426 def deleteKey(self, idKey): 427 """ Deletes a key from the set. May leave cMaxHits and cMinHits with outdated values. """ 428 self.cHits -= self.dcHitsPerId[idKey]; 429 del self.dcHitsPerId[idKey]; 430 if idKey in self.diPeriodFirst: 431 del self.diPeriodFirst[idKey]; 432 if idKey in self.diPeriodLast: 433 del self.diPeriodLast[idKey]; 434 if idKey in self.aoEnterInfo: 435 del self.aoEnterInfo[idKey]; 436 if idKey in self.aoLeaveInfo: 437 del self.aoLeaveInfo[idKey]; 438 del self.dSubjects[idKey]; 439 for oPeriod in self.aoPeriods: 440 oPeriod.helperSetDeleteKeyFromSet(idKey); 441 442 def pruneRowsWithZeroSumHits(self): 443 """ Discards rows with zero sum hits across all periods. Works around lazy selects counting both totals and hits. """ 444 fDeleted = False; 445 aidKeys = self.dcHitsPerId.keys(); 446 for idKey in aidKeys: 447 if self.dcHitsPerId[idKey] == 0: 448 self.deleteKey(idKey); 449 fDeleted = True; 450 if fDeleted: 451 self.recalcStats(); 335 452 336 453 def finalizePass1(self): … … 347 464 return self; 348 465 466 class ReportPeriodSetWithTotalBase(ReportPeriodSetBase): 467 """ In addition to the cHits, we also have a total to relate it too. """ 468 def __init__(self, sIdAttr): 469 ReportPeriodSetBase.__init__(self, sIdAttr); 470 self.dcTotalPerId = {}; # Sum total per subject ID (key). 471 self.cTotal = 0; # Sum number of total in all periods and all reasons. 472 self.cMaxTotal = 0; # Max total in a row. 473 self.cMinTotal = 0; # Min total in a row. 474 475 def _doStatsForPeriod(self, oPeriod): 476 assert isinstance(oPeriod, ReportPeriodWithTotalBase); 477 super(ReportPeriodSetWithTotalBase, self)._doStatsForPeriod(oPeriod); 478 self.cTotal += oPeriod.cTotal; 479 if oPeriod.cTotal > self.cMaxTotal: 480 self.cMaxTotal = oPeriod.cTotal; 481 if oPeriod.cTotal < self.cMinTotal: 482 self.cMinTotal = oPeriod.cTotal; 483 484 def recalcStats(self): 485 self.dcTotalPerId = {}; 486 self.cTotal = 0; 487 self.cMaxTotal = 0; 488 self.cMinTotal = 0; 489 super(ReportPeriodSetWithTotalBase, self).recalcStats(); 490 491 def deleteKey(self, idKey): 492 self.cTotal -= self.dcTotalPerId[idKey]; 493 del self.dcTotalPerId[idKey]; 494 super(ReportPeriodSetWithTotalBase, self).recalcStats(); 495 349 496 class ReportFailureReasonSet(ReportPeriodSetBase): 350 497 """ What ReportLazyModel.getFailureReasons returns. """ … … 352 499 ReportPeriodSetBase.__init__(self, 'idFailureReason'); 353 500 354 class ReportTestCaseFailureSet(ReportPeriodSet Base):501 class ReportTestCaseFailureSet(ReportPeriodSetWithTotalBase): 355 502 """ What ReportLazyModel.getTestCaseFailures returns. """ 356 503 def __init__(self): 357 ReportPeriodSetBase.__init__(self, 'idTestCase'); 358 504 ReportPeriodSetWithTotalBase.__init__(self, 'idTestCase'); 359 505 360 506 … … 570 716 for iPeriod in xrange(self.cPeriods): 571 717 self._oDb.execute('SELECT idTestCase,\n' 572 ' COUNT( idTestResult),\n'718 ' COUNT(CASE WHEN enmStatus >= \'failure\' THEN 1 END),\n' 573 719 ' MIN(tsDone),\n' 574 ' MAX(tsDone)\n' 720 ' MAX(tsDone),\n' 721 ' COUNT(idTestResult)\n' 575 722 'FROM TestSets\n' 576 723 'WHERE TRUE\n' … … 588 735 589 736 oSet.appendPeriod(oPeriod); 737 oSet.pruneRowsWithZeroSumHits(); 590 738 591 739 … … 635 783 'WHERE TestSets.idTestCase = %s\n' 636 784 ' AND TestSets.idBuild = Builds.idBuild\n' 637 ' AND Builds.tsExpire > TestSets.tsCreated\n' 638 ' AND Builds.tsEffective <= TestSets.tsCreated\n' 639 ' AND Builds.idBuildCategory = BuildCategories.idBuildCategory\n' 785 ' AND TestSets.enmStatus >= \'failure\'\n' 786 + self.getExtraWhereExprForPeriod(iPeriod) + 787 ' AND Builds.tsExpire > TestSets.tsCreated\n' 788 ' AND Builds.tsEffective <= TestSets.tsCreated\n' 789 ' AND Builds.idBuildCategory = BuildCategories.idBuildCategory\n' 640 790 'ORDER BY Builds.iRevision ' + sSorting + ',\n' 641 791 ' TestSets.tsCreated ' + sSorting + '\n'
Note:
See TracChangeset
for help on using the changeset viewer.