os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_stress_engine.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
/**
sl@0
    17
 @file
sl@0
    18
 @test
sl@0
    19
 @internalComponent - Internal Symbian test code
sl@0
    20
*/
sl@0
    21
sl@0
    22
#include <e32std.h>
sl@0
    23
#include <e32math.h>
sl@0
    24
#include <e32atomics.h>
sl@0
    25
#include "egltest_endpoint_engine.h"
sl@0
    26
#include "egltest_endpoint_stress_engine.h"
sl@0
    27
sl@0
    28
sl@0
    29
CStressTestEngine * CStressTestEngine::NewL(const TStressTestTable aStressTable[], TUint aNumTables)
sl@0
    30
    {
sl@0
    31
    CStressTestEngine *self = new (ELeave) CStressTestEngine;
sl@0
    32
    CleanupStack::PushL(self);
sl@0
    33
    self->ConstructL(aStressTable, aNumTables);
sl@0
    34
    CleanupStack::Pop(self);
sl@0
    35
    return self;
sl@0
    36
    }
sl@0
    37
sl@0
    38
sl@0
    39
void CStressTestEngine::ConstructL(const TStressTestTable aStressTable[], TUint aNumCases)
sl@0
    40
    {
sl@0
    41
    iStressTable = aStressTable;
sl@0
    42
    iNumCases = aNumCases;
sl@0
    43
    }
sl@0
    44
sl@0
    45
sl@0
    46
// DoPreamble - called from framework, set up list of Test IDs, so that we can
sl@0
    47
// mark them done later on - this is different from the regular 
sl@0
    48
//  CEglTest_Engine_Local code in that the data structure is different.
sl@0
    49
//
sl@0
    50
// Then call the common part with the regular CEglTest_Engine_Local 
sl@0
    51
void CStressTestEngine::DoPreambleL()
sl@0
    52
    {
sl@0
    53
    for(TInt curOuterCase = 0; curOuterCase < iNumCases; curOuterCase++)
sl@0
    54
        {
sl@0
    55
        const TTestCaseBase& innerCases = iStressTable[curOuterCase].iTestCaseBase;
sl@0
    56
        TPtrC testIds(innerCases.iRelatedTestIds);
sl@0
    57
        RegisterTestIdsL(testIds);
sl@0
    58
        }
sl@0
    59
    
sl@0
    60
    CommonPreambleL();
sl@0
    61
    }
sl@0
    62
sl@0
    63
// Derived function from CEglTest_Engine_Local, so that we can keep the local
sl@0
    64
// test result. 
sl@0
    65
void CStressTestEngine::DoPostambleL()
sl@0
    66
    {
sl@0
    67
    // Don't loose the verdict.
sl@0
    68
    TVerdict v = TestStepResult();
sl@0
    69
    CEgltest_Local_Engine::DoPostambleL();
sl@0
    70
    SetTestStepResult(v);
sl@0
    71
    }
sl@0
    72
sl@0
    73
CStressTestEngine::CStressTestEngine()
sl@0
    74
    {
sl@0
    75
    }
sl@0
    76
sl@0
    77
sl@0
    78
CStressTestEngine::~CStressTestEngine()
sl@0
    79
    {
sl@0
    80
    }
sl@0
    81
sl@0
    82
sl@0
    83
// Check if the entry needs modification, if so modify it. Modification is 
sl@0
    84
// indicated by presence of a flag bit and an index for which parameter
sl@0
    85
// to use. 
sl@0
    86
void CStressTestEngine::DoModifyL(TInt& aItem)
sl@0
    87
    {
sl@0
    88
    if (aItem & EExpandParamFlag)
sl@0
    89
        {
sl@0
    90
        TInt paramIndex = (aItem & EParamMask) >> EParamShift;
sl@0
    91
        if (!iParams[paramIndex])
sl@0
    92
            {
sl@0
    93
            ERR_PRINTF2(_L("Using undefined parameter PARAM%d"), paramIndex);
sl@0
    94
            User::Leave(KErrArgument);
sl@0
    95
            }
sl@0
    96
        User::LeaveIfNull(iParams[paramIndex]);
sl@0
    97
        aItem &= ERemoveFlagsMask;
sl@0
    98
        aItem += iParams[paramIndex]->Value();
sl@0
    99
        }
sl@0
   100
    }
sl@0
   101
sl@0
   102
sl@0
   103
// Modification of parameters of the testcase entry.
sl@0
   104
void CStressTestEngine::ModifyL(TEngineTestCase &aTestCase)
sl@0
   105
    {
sl@0
   106
    DoModifyL(aTestCase.iEndpointIndex);
sl@0
   107
    DoModifyL(aTestCase.iImageIndex);
sl@0
   108
    DoModifyL(aTestCase.iArg1);
sl@0
   109
    DoModifyL(aTestCase.iArg2);
sl@0
   110
    }
sl@0
   111
sl@0
   112
sl@0
   113
// Move to the next parameter for the parameter set.
sl@0
   114
void CStressTestEngine::NextParams()
sl@0
   115
    {
sl@0
   116
    for(TInt i = 0; i < KMaxParams; i++)
sl@0
   117
        {
sl@0
   118
        // Only update parameters that have been created.
sl@0
   119
        if (iParams[i])
sl@0
   120
            {
sl@0
   121
            iParams[i]->Next();
sl@0
   122
            }
sl@0
   123
        }
sl@0
   124
    }
sl@0
   125
sl@0
   126
sl@0
   127
// Create parameter set.
sl@0
   128
void CStressTestEngine::CreateParams(const TStressTestSection &aSection)
sl@0
   129
    {
sl@0
   130
    for(TInt i = 0; i < KMaxParams; i++)
sl@0
   131
        {
sl@0
   132
        ENGINE_ASSERT(!iParams[i]);
sl@0
   133
        iParams[i] = CStressParam::Factory(aSection.iParams[i]);
sl@0
   134
        }
sl@0
   135
    }
sl@0
   136
sl@0
   137
sl@0
   138
// Destroy parameter set.
sl@0
   139
void CStressTestEngine::DestroyParams()
sl@0
   140
    {
sl@0
   141
    for(TInt i = 0; i < KMaxParams; i++)
sl@0
   142
        {
sl@0
   143
        // It is harmless to delete a non-existant parameter, so 
sl@0
   144
        // no check needed.
sl@0
   145
        delete iParams[i];
sl@0
   146
        iParams[i] = NULL;
sl@0
   147
        }
sl@0
   148
    }
sl@0
   149
sl@0
   150
sl@0
   151
// Set the verdict for this operation on the local exec thread.
sl@0
   152
void CStressTestEngine::UpdateVerdict(TVerdict aVerdict)
sl@0
   153
    {
sl@0
   154
    TRemoteTestParams params;
sl@0
   155
    params.iEndpointEngine.iEngineTestCase.iCase = ESetVerdictCase;
sl@0
   156
    params.iEndpointEngine.iEngineTestCase.iEndpointIndex = EPass;
sl@0
   157
    TExecResult result;
sl@0
   158
    RunLocalTestCase(params, result);
sl@0
   159
    RunRemoteTestCase(ESetVerdictCase, params); 
sl@0
   160
    SetTestStepResult(aVerdict);
sl@0
   161
    }
sl@0
   162
sl@0
   163
sl@0
   164
// Look at the error value and update the verdict accordingly.
sl@0
   165
// Returns true if we should stop the iterating over the rest of the section.
sl@0
   166
// @param aSection - the section currently being executed.
sl@0
   167
// @param aCopy - the current iteration of the loop. 
sl@0
   168
// @param aCopies - total number of iterations to run. 
sl@0
   169
// @param aCurSection - numeric indication of the section. 
sl@0
   170
// @param aPreviousCopiesRun - updated according to policy to indicate how
sl@0
   171
//      many iterations to run the next section. 
sl@0
   172
TBool CStressTestEngine::HandleError(
sl@0
   173
        const TStressTestSection &aSection, 
sl@0
   174
        TInt aCopy, 
sl@0
   175
        TInt aCopies, 
sl@0
   176
        TInt aCurSection,
sl@0
   177
        TInt &aPreviousCopiesRun)
sl@0
   178
    {
sl@0
   179
    switch(aSection.iErrorPolicy)
sl@0
   180
        {
sl@0
   181
        case EOnErrorPolicyContinue:
sl@0
   182
            // Just let it pass...
sl@0
   183
            UpdateVerdict(EPass);
sl@0
   184
            break;
sl@0
   185
        case EOnErrorPolicyFail:
sl@0
   186
            // We should not have errors here.
sl@0
   187
            UpdateVerdict(EFail);
sl@0
   188
            break;
sl@0
   189
        case EOnErrorPolicyBreak:
sl@0
   190
            // Do not continue after errors.
sl@0
   191
            INFO_PRINTF4(_L("Ran only %d iterations of %d of section %d [not a failure]"), 
sl@0
   192
                    aCopy, aCopies, aCurSection);
sl@0
   193
            aPreviousCopiesRun = aCopy-1;
sl@0
   194
            UpdateVerdict(EPass);
sl@0
   195
            return ETrue;
sl@0
   196
        default:
sl@0
   197
            ENGINE_ASSERT(0);
sl@0
   198
            break;
sl@0
   199
        }
sl@0
   200
    return EFalse;
sl@0
   201
    }
sl@0
   202
sl@0
   203
// The main loop for the test. 
sl@0
   204
// Brief pseudo-code: 
sl@0
   205
// for each testcase
sl@0
   206
//   for each surface_type
sl@0
   207
//     for each section
sl@0
   208
//       for each copy of the section
sl@0
   209
//         perform engine operation
sl@0
   210
// Copy is really just an iteration. 
sl@0
   211
// The above pseudo-code is very simplified, but shows the overall flow. 
sl@0
   212
// Complications ommitted are:
sl@0
   213
// 1. We should adjust the number of iterations to run if there are errors.
sl@0
   214
// 2. We need to check for errors, and depending on circumstances, alter
sl@0
   215
//    the verdict.
sl@0
   216
TVerdict CStressTestEngine::doTestStepL()
sl@0
   217
    {
sl@0
   218
    INFO_PRINTF2(_L("Executing test with %d cases..."), iNumCases);
sl@0
   219
sl@0
   220
    for(TInt tests = 0; tests < iNumCases; tests++)
sl@0
   221
        {
sl@0
   222
        TTestCase tc;
sl@0
   223
        RDebug::Printf("%s:%d: tests = %d", __FILE__, __LINE__, tests);
sl@0
   224
        tc.iBase = iStressTable[tests].iTestCaseBase;
sl@0
   225
        TPtrC testIds(tc.iBase.iRelatedTestIds);
sl@0
   226
        SetCurrentTestIds(testIds);
sl@0
   227
        for(TInt surfIter= 0; surfIter < tc.iBase.iSurfaceTypeCount; surfIter++)
sl@0
   228
            {
sl@0
   229
            TInt previousCopiesRun = 1;
sl@0
   230
            TSurfaceType surfType = tc.iBase.iSurfaceTypeList[surfIter];
sl@0
   231
            
sl@0
   232
            INFO_PRINTF4(_L("Running testcase GRAPHICS-EGL-%s: %s (surf=%d)"),
sl@0
   233
                    tc.iBase.iRelatedTestIds, tc.iBase.iName, surfType);
sl@0
   234
sl@0
   235
            TRemoteTestParams configParams = {};
sl@0
   236
            configParams.iEndpointEngineConfig.iLogErrors = EFalse; 
sl@0
   237
            StartRemoteTestStep(configParams);
sl@0
   238
            
sl@0
   239
            for(TInt curSection = 0; curSection < iStressTable[tests].iNumSections; curSection++)
sl@0
   240
                {
sl@0
   241
                INFO_PRINTF3(_L("Section %d, result=%d"), curSection, TestStepResult());
sl@0
   242
                const TStressTestSection &section = iStressTable[tests].iSections[curSection];
sl@0
   243
                CreateParams(section);
sl@0
   244
                TInt copies = section.iIterations;
sl@0
   245
                if (section.iErrorPolicy == EOnErrorPolicyBreak)
sl@0
   246
                    {
sl@0
   247
                    if (section.iIterations != 1 && previousCopiesRun == 1)
sl@0
   248
                        {
sl@0
   249
                        previousCopiesRun = section.iIterations;
sl@0
   250
                        }
sl@0
   251
                    // We should not run more than iCopies times, but also not 
sl@0
   252
                    // allow previousCopiesRun to be zero to completely avoid 
sl@0
   253
                    // running a section.
sl@0
   254
                    copies = Min(section.iIterations, Max(previousCopiesRun, 1));
sl@0
   255
                    }
sl@0
   256
sl@0
   257
                for(TInt copy = 0; copy < copies; copy++)
sl@0
   258
                    {
sl@0
   259
                    // Make a copy and put it into the "tc" variable that we set up earlier....
sl@0
   260
                    TInt i = 0;
sl@0
   261
                    for(; section.iEngineTestCase[i].iCase != EFinishedCase; i++)
sl@0
   262
                        {
sl@0
   263
                        TEngineTestCase ec = section.iEngineTestCase[i];
sl@0
   264
                        ModifyL(ec);
sl@0
   265
                        tc.iEngineTestCase[i] = ec;
sl@0
   266
                        }
sl@0
   267
                    tc.iEngineTestCase[i].iCase = EFinishedCase;
sl@0
   268
                    TRAPD(err, RunSingleCaseL(tc, surfType));
sl@0
   269
                    if (err != KErrNone)
sl@0
   270
                        {
sl@0
   271
                        INFO_PRINTF2(_L("RunSingleCaseL left with an error: %d"), err);
sl@0
   272
                        }
sl@0
   273
                    if (err != KErrNone || TestStepResult() != EPass)
sl@0
   274
                        {
sl@0
   275
                        if (HandleError(section, copy, copies, 
sl@0
   276
                                curSection, previousCopiesRun))
sl@0
   277
                            {
sl@0
   278
                            break;
sl@0
   279
                            }
sl@0
   280
                        }
sl@0
   281
                    NextParams();
sl@0
   282
                    }
sl@0
   283
                DestroyParams();
sl@0
   284
                }              
sl@0
   285
            // params are not used in this call, so we just pass some suitable type in.
sl@0
   286
            // Save the result, as the remote side may have failed, but it's
sl@0
   287
            // not a real failure in a stress-test.
sl@0
   288
            TVerdict v = TestStepResult();
sl@0
   289
            EndRemoteTestStep(configParams);
sl@0
   290
            SetTestStepResult(v);
sl@0
   291
            }
sl@0
   292
        }
sl@0
   293
    return TestStepResult();
sl@0
   294
    }
sl@0
   295
sl@0
   296
sl@0
   297
sl@0
   298
sl@0
   299
// Derived function to start a thread. 
sl@0
   300
void CStressTestEngine::StartThreadL(TInt aThreadNumber)
sl@0
   301
    {
sl@0
   302
    const TInt KStackSize = 12000;
sl@0
   303
    const TInt KHeapMinSize = 16000;
sl@0
   304
    const TInt KHeapMaxSize = 1000000;
sl@0
   305
sl@0
   306
    if (aThreadNumber >= KMaxLoadThreads)
sl@0
   307
        {
sl@0
   308
        User::Panic(_L("StartThreadL"), __LINE__);
sl@0
   309
        }
sl@0
   310
    
sl@0
   311
    __e32_atomic_store_rel32(&iStopThreadFlag[aThreadNumber], EFalse);
sl@0
   312
    TUint32 random = Math::Random();
sl@0
   313
    TName threadName;
sl@0
   314
    _LIT(KThreadNameFormat, "%S-%u");
sl@0
   315
sl@0
   316
    // Create a loadthread. 
sl@0
   317
    _LIT(KThreadName, "EpTestLoadThread");
sl@0
   318
    threadName.Format(KThreadNameFormat, &KThreadName, random);
sl@0
   319
    TThreadFunction threadFunc = GetThreadFunction(aThreadNumber);
sl@0
   320
    if (threadFunc == NULL)
sl@0
   321
        {
sl@0
   322
        ERR_PRINTF2(_L("Requested thread function %d, got NULL pointer back!"), aThreadNumber);
sl@0
   323
        User::Leave(KErrArgument);
sl@0
   324
        }
sl@0
   325
    TInt err = iLoadThread[aThreadNumber].Create(threadName, threadFunc, 
sl@0
   326
                    KStackSize, KHeapMinSize, KHeapMaxSize, this, EOwnerThread);
sl@0
   327
    if(err != KErrNone)
sl@0
   328
        {
sl@0
   329
        ERR_PRINTF2(_L("Could not create load thread - err=%d"), err);
sl@0
   330
        User::Leave(err);
sl@0
   331
        }
sl@0
   332
    iLoadThread[aThreadNumber].Resume();
sl@0
   333
    }
sl@0
   334
sl@0
   335
sl@0
   336
// Terminate a previously started thread.
sl@0
   337
void CStressTestEngine::EndThread(TInt aThreadNumber)
sl@0
   338
    {
sl@0
   339
    TRequestStatus status;
sl@0
   340
    iLoadThread[aThreadNumber].Logon(status);
sl@0
   341
    RDebug::Printf("Ending thread %d", aThreadNumber);
sl@0
   342
    __e32_atomic_store_rel32(&iStopThreadFlag[aThreadNumber], ETrue);
sl@0
   343
    // Wait for thread to exit.
sl@0
   344
    User::WaitForRequest(status);
sl@0
   345
    iLoadThread[aThreadNumber].Close();
sl@0
   346
    }
sl@0
   347
sl@0
   348
// This function is intended to be implemented by a derived class - just print
sl@0
   349
// an error and return NULL.   
sl@0
   350
TThreadFunction CStressTestEngine::GetThreadFunction(TInt aThreadNumber)
sl@0
   351
    {
sl@0
   352
    ERR_PRINTF2(_L("Should not be called: CStressTestEngine::GetThreadFunction() with %d"), aThreadNumber);
sl@0
   353
    return NULL;
sl@0
   354
    }
sl@0
   355
sl@0
   356
sl@0
   357
// Parameter class implementation.
sl@0
   358
// General description:
sl@0
   359
// The class uses a virtual interface that has three member functions:
sl@0
   360
// Initialize(start, end, step) 
sl@0
   361
//   Setup. The values of start, end and step may be used for other purposes
sl@0
   362
// Value()
sl@0
   363
//   Return current value of the parameter. Does not alter the value.
sl@0
   364
// Next()
sl@0
   365
//   Update the value to the next one. Where relevant, wrap around to the 
sl@0
   366
//   starting value if the end has been reached.
sl@0
   367
sl@0
   368
// Factory function to create parameter instances.
sl@0
   369
CStressParam * CStressParam::Factory(const TParamDeclaration &aParamDecl)
sl@0
   370
    {
sl@0
   371
    CStressParam *p;
sl@0
   372
    switch(aParamDecl.iType)
sl@0
   373
        {
sl@0
   374
        case EParamTypeNone:
sl@0
   375
            // Didn't want this parameter - return NULL!
sl@0
   376
            // We later check if the pointer is NULL and complain if an
sl@0
   377
            // attempt is made to USE this parameter.
sl@0
   378
            p = NULL;
sl@0
   379
            break;
sl@0
   380
            
sl@0
   381
        case EParamTypeIterator:
sl@0
   382
            p = new CStressParamIterator;
sl@0
   383
            break;
sl@0
   384
            
sl@0
   385
        case EParamTypeTable:
sl@0
   386
            p = new CStressParamTable;
sl@0
   387
            break;
sl@0
   388
            
sl@0
   389
        case EParamTypeRandomizer:
sl@0
   390
            p = new CStressParamRandomizer;
sl@0
   391
            break;
sl@0
   392
            
sl@0
   393
        default:
sl@0
   394
            RDebug::Printf("%s:%d: Type not implemented (type = %d)", 
sl@0
   395
                    __FILE__, __LINE__, aParamDecl.iType);
sl@0
   396
            p = NULL;
sl@0
   397
            break;
sl@0
   398
        }
sl@0
   399
    if (p)
sl@0
   400
        {
sl@0
   401
        p->Initialize(aParamDecl.iInit, aParamDecl.iEnd, aParamDecl.iStep);
sl@0
   402
        }
sl@0
   403
    return p;
sl@0
   404
    }
sl@0
   405
sl@0
   406
sl@0
   407
CStressParam::~CStressParam()
sl@0
   408
    {
sl@0
   409
    }
sl@0
   410
sl@0
   411
sl@0
   412
CStressParamIterator::CStressParamIterator()
sl@0
   413
    {
sl@0
   414
    }
sl@0
   415
sl@0
   416
sl@0
   417
CStressParamIterator::~CStressParamIterator()
sl@0
   418
    {
sl@0
   419
    }
sl@0
   420
sl@0
   421
sl@0
   422
void CStressParamIterator::Initialize(TInt aInit, TInt aEnd, TInt aStep)
sl@0
   423
    {
sl@0
   424
    iInit = aInit;
sl@0
   425
    iEnd = aEnd;
sl@0
   426
    iStep = aStep;
sl@0
   427
    iIterator = iInit;
sl@0
   428
    }
sl@0
   429
sl@0
   430
void CStressParamIterator::Next()
sl@0
   431
    {
sl@0
   432
    iIterator += iStep;
sl@0
   433
    if (iStep > 0)
sl@0
   434
        {
sl@0
   435
        if (iIterator >= iEnd)
sl@0
   436
            {
sl@0
   437
            iIterator = iInit;
sl@0
   438
            }
sl@0
   439
        }
sl@0
   440
    else
sl@0
   441
        {
sl@0
   442
        if (iIterator <= iEnd)
sl@0
   443
            {
sl@0
   444
            iIterator = iInit;
sl@0
   445
            }
sl@0
   446
        }
sl@0
   447
    }
sl@0
   448
sl@0
   449
sl@0
   450
TInt CStressParamIterator::Value()
sl@0
   451
    {
sl@0
   452
    return iIterator;
sl@0
   453
    }
sl@0
   454
sl@0
   455
sl@0
   456
CStressParamRandomizer::CStressParamRandomizer()
sl@0
   457
    {
sl@0
   458
    }
sl@0
   459
sl@0
   460
sl@0
   461
CStressParamRandomizer::~CStressParamRandomizer()
sl@0
   462
    {
sl@0
   463
    }
sl@0
   464
sl@0
   465
sl@0
   466
void CStressParamRandomizer::Initialize(TInt aMin, TInt aMax, TInt aMul)
sl@0
   467
    {
sl@0
   468
    iMin = aMin;
sl@0
   469
    iMax = aMax;
sl@0
   470
    iMul = aMul;
sl@0
   471
    // Now, pick a new random number. 
sl@0
   472
    Next();  
sl@0
   473
    }
sl@0
   474
sl@0
   475
sl@0
   476
void CStressParamRandomizer::Next()
sl@0
   477
    {
sl@0
   478
    iCurrent = (((TInt)Math::Random()) % ((iMax - iMin) + iMin)) * iMul;
sl@0
   479
    }
sl@0
   480
sl@0
   481
TInt CStressParamRandomizer::Value()
sl@0
   482
    {
sl@0
   483
    return iCurrent;
sl@0
   484
    }
sl@0
   485
sl@0
   486
sl@0
   487
CStressParamTable::CStressParamTable()
sl@0
   488
    {
sl@0
   489
    }
sl@0
   490
sl@0
   491
sl@0
   492
CStressParamTable::~CStressParamTable()
sl@0
   493
    {
sl@0
   494
    }
sl@0
   495
sl@0
   496
sl@0
   497
void CStressParamTable::Initialize(TInt aTable, TInt aCount, TInt /* aUnused */)
sl@0
   498
    {
sl@0
   499
    iTable = reinterpret_cast<TInt *>(aTable);
sl@0
   500
    iCount = aCount;
sl@0
   501
    iIndex = 0;
sl@0
   502
    }
sl@0
   503
sl@0
   504
sl@0
   505
void CStressParamTable::Next()
sl@0
   506
    {
sl@0
   507
    iIndex = (iIndex + 1) % iCount;
sl@0
   508
    }
sl@0
   509
sl@0
   510
sl@0
   511
TInt CStressParamTable::Value()
sl@0
   512
    {
sl@0
   513
    return iTable[iIndex];
sl@0
   514
    }