VirtualBox

Ignore:
Timestamp:
May 29, 2016 12:34:45 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
107562
Message:

testmanager: Generate list of test cases starting (and stopping) to fail, with failure count graph.

File:
1 edited

Legend:

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

    r61269 r61270  
    3636from testmanager.core.failurereason import FailureReasonLogic;
    3737from testmanager.core.testbox       import TestBoxData;
     38from testmanager.core.testcase      import TestCaseLogic;
    3839from common                         import constants;
    3940
     
    7576        # Public so the report generator can easily access them.
    7677        self.tsNow           = tsNow;               # (Can be None.)
     78        self.__tsNowDateTime = None;
    7779        self.cPeriods        = cPeriods;
    7880        self.cHoursPerPeriod = cHoursPerPeriod;
     
    127129        return sWhere;
    128130
     131    def getNowAsDateTime(self):
     132        """ Returns a datetime instance corresponding to tsNow. """
     133        if self.__tsNowDateTime is None:
     134            if self.tsNow is None:
     135                self.__tsNowDateTime = self._oDb.getCurrentTimestamp();
     136            else:
     137                self._oDb.execute('SELECT %s::TIMESTAMP WITH TIME ZONE', (self.tsNow,));
     138                self.__tsNowDateTime = self._oDb.fetchOne()[0];
     139        return self.__tsNowDateTime;
     140
    129141    def getPeriodStart(self, iPeriod):
    130142        """ Gets the python timestamp for the start of the given period. """
    131143        from datetime import timedelta;
    132         tsNow = self.tsNow if self.tsNow is not None else self._oDb.getCurrentTimestamp();
    133144        cHoursStart = (self.cPeriods - iPeriod    ) * self.cHoursPerPeriod;
    134         return tsNow - timedelta(hours = cHoursStart);
     145        return self.getNowAsDateTime() - timedelta(hours = cHoursStart);
    135146
    136147    def getPeriodEnd(self, iPeriod):
    137148        """ Gets the python timestamp for the end of the given period. """
    138149        from datetime import timedelta;
    139         tsNow = self.tsNow if self.tsNow is not None else self._oDb.getCurrentTimestamp();
    140150        cHoursEnd   = (self.cPeriods - iPeriod - 1) * self.cHoursPerPeriod;
    141         return tsNow - timedelta(hours = cHoursEnd);
     151        return self.getNowAsDateTime() - timedelta(hours = cHoursEnd);
    142152
    143153    def getExtraWhereExprForPeriod(self, iPeriod):
     
    180190
    181191
    182 class ReportFailureReasonRow(object):
    183     """ Simpler to return this than muck about with stupid arrays. """
    184     def __init__(self, aoRow, oReason):
    185         self.idFailureReason    = aoRow[0];
    186         self.cHits              = aoRow[1];
    187         self.tsMin              = aoRow[2];
    188         self.tsMax              = aoRow[3];
    189         self.oReason            = oReason; # FailureReasonDataEx
    190 
    191 class ReportFailureReasonTransient(object):
    192     """ Details the first or last occurence of a reason.  """
    193     def __init__(self, idBuild, iRevision, sRepository, idTestSet, idTestResult, tsDone,  # pylint: disable=R0913
    194                  oReason, iPeriod, fEnter):
     192#
     193# Data structures produced and returned by the ReportLazyModel.
     194#
     195
     196class ReportTransientBase(object):
     197    """ Details on the test where a problem was first/last seen.  """
     198    def __init__(self, idBuild, iRevision, sRepository, idTestSet, idTestResult, tsDone, iPeriod, fEnter):
    195199        self.idBuild            = idBuild;      # Build ID.
    196200        self.iRevision          = iRevision;    # SVN revision for build.
     
    199203        self.idTestResult       = idTestResult; # Test result.
    200204        self.tsDone             = tsDone;       # When the test set was done.
    201         self.oReason            = oReason;      # FailureReasonDataEx
    202205        self.iPeriod            = iPeriod;      # Data set period.
    203206        self.fEnter             = fEnter;       # True if enter event, False if leave event.
    204207
    205 class ReportFailureReasonPeriod(object):
     208class ReportFailureReasonTransient(ReportTransientBase):
     209    """ Details on the test where a failure reason was first/last seen.  """
     210    def __init__(self, idBuild, iRevision, sRepository, idTestSet, idTestResult, tsDone,  # pylint: disable=R0913
     211                 iPeriod, fEnter, oReason):
     212        ReportTransientBase.__init__(self, idBuild, iRevision, sRepository, idTestSet, idTestResult, tsDone, iPeriod, fEnter);
     213        self.oReason            = oReason;      # FailureReasonDataEx
     214
     215class ReportTestCaseFailureTransient(ReportTransientBase):
     216    """ Details on the test where a test case was first/last seen.  """
     217    def __init__(self, idBuild, iRevision, sRepository, idTestSet, idTestResult, tsDone,  # pylint: disable=R0913
     218                 iPeriod, fEnter, oTestCase):
     219        ReportTransientBase.__init__(self, idBuild, iRevision, sRepository, idTestSet, idTestResult, tsDone, iPeriod, fEnter);
     220        self.oTestCase          = oTestCase;      # TestCaseDataEx
     221
     222
     223class ReportHitRowBase(object):
     224    """ A row in a period. """
     225    def __init__(self, cHits, tsMin = None, tsMax = None):
     226        self.cHits              = cHits;
     227        self.tsMin              = tsMin;
     228        self.tsMax              = tsMax;
     229
     230class ReportFailureReasonRow(ReportHitRowBase):
     231    """ The account of one failure reason for a period. """
     232    def __init__(self, aoRow, oReason):
     233        ReportHitRowBase.__init__(self, aoRow[1], aoRow[2], aoRow[3]);
     234        self.idFailureReason    = aoRow[0];
     235        self.oReason            = oReason;      # FailureReasonDataEx
     236
     237class ReportTestCaseFailureRow(ReportHitRowBase):
     238    """ 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
     243
     244
     245class ReportPeriodBase(object):
    206246    """ A period in ReportFailureReasonSet. """
    207247    def __init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo):
    208         self.oSet               = oSet          # Reference to the parent ReportFailureReasonSet.
    209         self.iPeriod            = iPeriod;
    210         self.sDesc              = sDesc;
    211         self.aoRows             = [];           # Rows in order the database returned them.
    212         self.dById              = {};           # Same as aoRows but indexed by idFailureReason.
    213         self.cHits              = 0;            # Total number of hits.
    214         self.dFirst             = {};           # The reasons seen for the first time (idFailureReason key).
    215         self.dLast              = {};           # The reasons seen for the last time (idFailureReason key).
    216         self.tsStart            = tsFrom;
    217         self.tsEnd              = tsTo;
    218         self.tsMin              = tsTo;
    219         self.tsMax              = tsFrom;
     248        self.oSet               = oSet          # Reference to the parent ReportSetBase derived object.
     249        self.iPeriod            = iPeriod;      # Period number in the set.
     250        self.sDesc              = sDesc;        # Short period description.
     251        self.tsStart            = tsFrom;       # Start of the period.
     252        self.tsEnd              = tsTo;         # End of the period (exclusive).
     253        self.tsMin              = tsTo;         # The earlierst hit of the period (only valid for cHits > 0).
     254        self.tsMax              = tsFrom;       # The latest hit of the period (only valid for cHits > 0).
     255        self.aoRows             = [];           # Rows in order the database returned them (ReportHitRowBase descendant).
     256        self.dRowsById          = {};           # Same as aoRows but indexed by object ID (see ReportSetBase::sIdAttr).
     257        self.dFirst             = {};           # The subjects seen for the first time - data object, keyed by ID.
     258        self.dLast              = {};           # The subjects seen for the last  time - data object, keyed by ID.
     259        self.cHits              = 0;            # Total number of hits in this period.
     260        self.cMaxHits           = 0;            # Max hits in a row.
     261        self.cMinHits           = 99999999;     # Min hits in a row (only valid for cHits > 0).
     262
     263    def appendRow(self, oRow, idRow, oData):
     264        """ Adds a row. """
     265        assert isinstance(oRow, ReportHitRowBase);
     266        self.aoRows.append(oRow);
     267        self.dRowsById[idRow] = oRow;
     268
     269        if oRow.tsMin is not None and oRow.tsMin < self.tsMin:
     270            self.tsMin = oRow.tsMin;
     271        if oRow.tsMax is not None and oRow.tsMax < self.tsMax:
     272            self.tsMax = oRow.tsMax;
     273
     274        self.cHits += oRow.cHits;
     275        if oRow.cHits > self.cMaxHits:
     276            self.cMaxHits = oRow.cHits;
     277        if oRow.cHits < self.cMinHits:
     278            self.cMinHits = oRow.cHits;
     279
     280        if idRow in self.oSet.dcTotalsPerId:
     281            self.oSet.dcTotalsPerId[idRow] += oRow.cHits;
     282        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;
     288
     289class ReportFailureReasonPeriod(ReportPeriodBase):
     290    """ A period in ReportFailureReasonSet. """
     291    def __init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo):
     292        ReportPeriodBase.__init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo);
    220293        self.cWithoutReason     = 0;            # Number of failed test sets without any assigned reason.
    221294
    222 class ReportFailureReasonSet(object):
     295class ReportTestCaseFailurePeriod(ReportPeriodBase):
     296    """ A period in ReportTestCaseFailureSet. """
     297    def __init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo):
     298        ReportPeriodBase.__init__(self, oSet, iPeriod, sDesc, tsFrom, tsTo);
     299
     300
     301class ReportPeriodSetBase(object):
     302    """ Period data set base class. """
     303    def __init__(self, sIdAttr):
     304        self.sIdAttr            = sIdAttr;      # The name of the key attribute.  Mainly for documentation purposes.
     305        self.aoPeriods          = [];           # Periods (ReportPeriodBase descendant) in ascending order (time wise).
     306        self.dcTotalsPerId      = {};           # Totals per subject ID (key).
     307        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.
     309        self.cMaxHits           = 0;            # Max hits in a row.
     310        self.cMinHits           = 0;            # Min hits in a row.
     311        self.cMaxRows           = 0;            # Max number of rows in a period.
     312        self.cMinRows           = 0;            # Min number of rows in a period.
     313        self.diPeriodFirst      = {};           # The period number a reason was first seen (keyed by subject ID).
     314        self.diPeriodLast       = {};           # The period number a reason was last seen (keyed by subject ID).
     315        self.aoEnterInfo        = [];           # Array of ReportTransientBase children order by iRevision.  Excludes
     316                                                # the first period of course.  (Child class populates this.)
     317        self.aoLeaveInfo        = [];           # Array of ReportTransientBase children order in descending order by
     318                                                # iRevision. Excludes the last priod.  (Child class populates this.)
     319
     320    def appendPeriod(self, oPeriod):
     321        """ Appends a period to the set. """
     322        assert isinstance(oPeriod, ReportPeriodBase);
     323        self.aoPeriods.append(oPeriod);
     324
     325        self.cHits += oPeriod.cHits;
     326        if oPeriod.cHits > self.cMaxHits:
     327            self.cMaxHits = oPeriod.cHits;
     328        if oPeriod.cHits < self.cMinHits:
     329            self.cMinHits = oPeriod.cHits;
     330
     331        if len(oPeriod.aoRows) > self.cMaxHits:
     332            self.cMaxHits = len(oPeriod.aoRows);
     333        if len(oPeriod.aoRows) < self.cMinHits:
     334            self.cMinHits = len(oPeriod.aoRows);
     335
     336    def finalizePass1(self):
     337        """ Finished all but aoEnterInfo and aoLeaveInfo. """
     338        # All we need to do here is to populate the dLast members.
     339        for idKey, iPeriod in self.diPeriodLast.items():
     340            self.aoPeriods[iPeriod].dLast[idKey] = self.dSubjects[idKey];
     341        return self;
     342
     343    def finalizePass2(self):
     344        """ Called after aoEnterInfo and aoLeaveInfo has been populated to sort them. """
     345        self.aoEnterInfo = sorted(self.aoEnterInfo, key = lambda oTrans: oTrans.iRevision);
     346        self.aoLeaveInfo = sorted(self.aoLeaveInfo, key = lambda oTrans: oTrans.iRevision, reverse = True);
     347        return self;
     348
     349class ReportFailureReasonSet(ReportPeriodSetBase):
    223350    """ What ReportLazyModel.getFailureReasons returns. """
    224351    def __init__(self):
    225         self.aoPeriods   = [];  # Periods in ascending order (time wise).
    226         self.dReasons    = {};  # FailureReasonDataEx objected indexted by idFailureReason
    227         self.dTotals     = {};  # Totals per reason, indexed by idFailureReason.
    228         self.cHits       = 0;   # Total number of hits in all periods and all reasons.
    229         self.cMaxRowHits = 0;   # Max hits in a row.
    230         self.diFirst     = {};  # The period number a reason was first seen (idFailureReason key).
    231         self.diLast      = {};  # The period number a reason was last seen (idFailureReason key).
    232         self.aoEnterInfo = [];  # Array of ReportFailureReasonTransient order by iRevision. Excludes the first period.
    233         self.aoLeaveInfo = [];  # Array of ReportFailureReasonTransient order in descending order by iRevision.  Excludes last.
     352        ReportPeriodSetBase.__init__(self, 'idFailureReason');
     353
     354class ReportTestCaseFailureSet(ReportPeriodSetBase):
     355    """ What ReportLazyModel.getTestCaseFailures returns. """
     356    def __init__(self):
     357        ReportPeriodSetBase.__init__(self, 'idTestCase');
    234358
    235359
     
    300424        Gets the failure reasons of the subject in the specified period.
    301425
    302         Returns an array of data per period (0 is the oldes, self.cPeriods-1 is
    303         the latest) where each entry is a dicationary using failure reason ID as
    304         key.  The dictionary contains a tuple where the first element is the
    305         number of occurences and the second is the corresponding
    306         FailureReasonDataEx object from the cache.
    307 
    308         Note that reason IDs may not be present in every period, we only return
    309         those with actual occurences.
    310         """
     426        Returns a ReportFailureReasonSet instance.
     427        """
     428
     429        oFailureReasonLogic = FailureReasonLogic(self._oDb);
    311430
    312431        # Create a temporary table
     
    337456        self._oDb.execute('SELECT idFailureReason FROM TmpReasons;');
    338457
    339 
    340458        # Retrieve the period results.
    341         oFailureReasonLogic = FailureReasonLogic(self._oDb);
    342459        oSet = ReportFailureReasonSet();
    343460        for iPeriod in xrange(self.cPeriods):
     
    354471            oPeriod = ReportFailureReasonPeriod(oSet, iPeriod, self.getStraightPeriodDesc(iPeriod),
    355472                                                self.getPeriodStart(iPeriod), self.getPeriodEnd(iPeriod));
    356             oSet.aoPeriods.append(oPeriod);
     473
    357474            for aoRow in aaoRows:
    358475                oReason = oFailureReasonLogic.cachedLookup(aoRow[0]);
    359476                oPeriodRow = ReportFailureReasonRow(aoRow, oReason);
    360                 oPeriod.aoRows.append(oPeriodRow);
    361                 oPeriod.dById[oPeriodRow.idFailureReason] = oPeriodRow;
    362                 oPeriod.cHits += oPeriodRow.cHits;
    363                 if oPeriodRow.idFailureReason in oSet.dReasons:
    364                     oSet.dTotals[oPeriodRow.idFailureReason]  += oPeriodRow.cHits;
    365                 else:
    366                     oSet.dTotals[oPeriodRow.idFailureReason]   = oPeriodRow.cHits;
    367                     oSet.dReasons[oPeriodRow.idFailureReason]  = oReason;
    368                     oSet.diFirst[oPeriodRow.idFailureReason]   = iPeriod;
    369                     oPeriod.dFirst[oPeriodRow.idFailureReason] = oReason;
    370                 if oPeriodRow.cHits > oSet.cMaxRowHits:
    371                     oSet.cMaxRowHits = oPeriodRow.cHits;
    372                 if oPeriodRow.tsMin < oPeriod.tsMin:
    373                     oPeriod.tsMin = oPeriodRow.tsMin;
    374                 if oPeriodRow.tsMax > oPeriod.tsMax:
    375                     oPeriod.tsMax = oPeriodRow.tsMax;
    376             oSet.cHits += oPeriod.cHits;
     477                oPeriod.appendRow(oPeriodRow, oReason.idFailureReason, oReason);
    377478
    378479            # Count how many test sets we've got without any reason associated with them.
     
    388489            oPeriod.cWithoutReason = self._oDb.fetchOne()[0];
    389490
    390 
    391         #
    392         # construct the diLast and dLast bits.
    393         #
    394         for iPeriod in xrange(self.cPeriods - 1, 0, -1):
    395             oPeriod = oSet.aoPeriods[iPeriod];
    396             for oRow in oPeriod.aoRows:
    397                 if oRow.idFailureReason not in oSet.diLast:
    398                     oSet.diLast[oRow.idFailureReason]   = iPeriod;
    399                     oPeriod.dLast[oRow.idFailureReason] = oRow.oReason;
     491            oSet.appendPeriod(oPeriod);
     492
    400493
    401494        #
     
    403496        # test set it first occured with.
    404497        #
     498        oSet.finalizePass1();
     499
    405500        for iPeriod in xrange(1, self.cPeriods):
    406501            oPeriod = oSet.aoPeriods[iPeriod];
    407502            for oReason in oPeriod.dFirst.values():
    408503                oSet.aoEnterInfo.append(self._getEdgeFailureReasonOccurence(oReason, iPeriod, fEnter = True));
    409         oSet.aoEnterInfo = sorted(oSet.aoEnterInfo, key = lambda oTrans: oTrans.iRevision);
    410504
    411505        # Ditto for reasons leaving before the last.
     
    414508            for oReason in oPeriod.dLast.values():
    415509                oSet.aoLeaveInfo.append(self._getEdgeFailureReasonOccurence(oReason, iPeriod, fEnter = False));
    416         oSet.aoLeaveInfo = sorted(oSet.aoLeaveInfo, key = lambda oTrans: oTrans.iRevision, reverse = True);
     510
     511        oSet.finalizePass2();
    417512
    418513        self._oDb.execute('DROP TABLE TmpReasons\n');
     
    431526
    432527        """
     528
     529
    433530        sSorting = 'ASC' if fEnter else 'DESC';
    434531        self._oDb.execute('SELECT   TmpReasons.idTestResult,\n'
     
    452549        aoRow = self._oDb.fetchOne();
    453550        if aoRow is None:
    454             return ReportFailureReasonTransient(-1, -1, 'internal-error', -1, -1,
    455                                                 self._oDb.getCurrentTimestamp(), oReason, iPeriod, fEnter);
     551            return ReportFailureReasonTransient(-1, -1, 'internal-error', -1, -1, self._oDb.getCurrentTimestamp(),
     552                                                iPeriod, fEnter, oReason);
    456553        return ReportFailureReasonTransient(idBuild = aoRow[3], iRevision = aoRow[4], sRepository = aoRow[5],
    457554                                            idTestSet = aoRow[1], idTestResult = aoRow[0], tsDone = aoRow[2],
    458                                             oReason = oReason, iPeriod = iPeriod, fEnter = fEnter);
     555                                            iPeriod = iPeriod, fEnter = fEnter, oReason = oReason);
     556
     557
     558    def getTestCaseFailures(self):
     559        """
     560        Gets the test case failures of the subject in the specified period.
     561
     562        Returns a ReportTestCaseFailureSet instance.
     563
     564        """
     565
     566        oTestCaseLogic = TestCaseLogic(self._oDb);
     567
     568        # Retrieve the period results.
     569        oSet = ReportTestCaseFailureSet();
     570        for iPeriod in xrange(self.cPeriods):
     571            self._oDb.execute('SELECT   idTestCase,\n'
     572                              '         COUNT(idTestResult),\n'
     573                              '         MIN(tsDone),\n'
     574                              '         MAX(tsDone)\n'
     575                              'FROM     TestSets\n'
     576                              'WHERE    TRUE\n'
     577                              + self.getExtraWhereExprForPeriod(iPeriod) +
     578                              'GROUP BY idTestCase\n');
     579            aaoRows = self._oDb.fetchAll()
     580
     581            oPeriod = ReportTestCaseFailurePeriod(oSet, iPeriod, self.getStraightPeriodDesc(iPeriod),
     582                                                  self.getPeriodStart(iPeriod), self.getPeriodEnd(iPeriod));
     583
     584            for aoRow in aaoRows:
     585                oTestCase = oTestCaseLogic.cachedLookup(aoRow[0]);
     586                oPeriodRow = ReportTestCaseFailureRow(aoRow, oTestCase);
     587                oPeriod.appendRow(oPeriodRow, oTestCase.idTestCase, oTestCase);
     588
     589            oSet.appendPeriod(oPeriod);
     590
     591
     592        #
     593        # For reasons entering after the first period, look up the build and
     594        # test set it first occured with.
     595        #
     596        oSet.finalizePass1();
     597
     598        for iPeriod in xrange(1, self.cPeriods):
     599            oPeriod = oSet.aoPeriods[iPeriod];
     600            for oTestCase in oPeriod.dFirst.values():
     601                oSet.aoEnterInfo.append(self._getEdgeTestCaseFailureOccurence(oTestCase, iPeriod, fEnter = True));
     602
     603        # Ditto for reasons leaving before the last.
     604        for iPeriod in xrange(self.cPeriods - 1):
     605            oPeriod = oSet.aoPeriods[iPeriod];
     606            for oTestCase in oPeriod.dLast.values():
     607                oSet.aoLeaveInfo.append(self._getEdgeTestCaseFailureOccurence(oTestCase, iPeriod, fEnter = False));
     608
     609        oSet.finalizePass2();
     610
     611        return oSet;
     612
     613
     614    def _getEdgeTestCaseFailureOccurence(self, oTestCase, iPeriod, fEnter = True):
     615        """
     616        Helper for the failure reason report that finds the oldest or newest build
     617        (SVN rev) and test set (start time) it occured with.
     618
     619        If fEnter is set the oldest occurence is return, if fEnter clear the newest
     620        is is returned.
     621
     622        Returns ReportFailureReasonTransient instant.
     623
     624        """
     625        sSorting = 'ASC' if fEnter else 'DESC';
     626        self._oDb.execute('SELECT   TestSets.idTestResult,\n'
     627                          '         TestSets.idTestSet,\n'
     628                          '         TestSets.tsDone,\n'
     629                          '         TestSets.idBuild,\n'
     630                          '         Builds.iRevision,\n'
     631                          '         BuildCategories.sRepository\n'
     632                          'FROM     TestSets,\n'
     633                          '         Builds,\n'
     634                          '         BuildCategories\n'
     635                          'WHERE    TestSets.idTestCase       = %s\n'
     636                          '     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'
     640                          'ORDER BY Builds.iRevision ' + sSorting + ',\n'
     641                          '         TestSets.tsCreated ' + sSorting + '\n'
     642                          'LIMIT 1\n'
     643                          , ( oTestCase.idTestCase, ));
     644        aoRow = self._oDb.fetchOne();
     645        if aoRow is None:
     646            return ReportTestCaseFailureTransient(-1, -1, 'internal-error', -1, -1,
     647                                                  self._oDb.getCurrentTimestamp(), oTestCase, iPeriod, fEnter);
     648        return ReportTestCaseFailureTransient(idBuild = aoRow[3], iRevision = aoRow[4], sRepository = aoRow[5],
     649                                              idTestSet = aoRow[1], idTestResult = aoRow[0], tsDone = aoRow[2],
     650                                              oTestCase = oTestCase, iPeriod = iPeriod, fEnter = fEnter);
    459651
    460652
Note: See TracChangeset for help on using the changeset viewer.

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