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