os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_stress_engine.cpp
Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
19 @internalComponent - Internal Symbian test code
24 #include <e32atomics.h>
25 #include "egltest_endpoint_engine.h"
26 #include "egltest_endpoint_stress_engine.h"
29 CStressTestEngine * CStressTestEngine::NewL(const TStressTestTable aStressTable[], TUint aNumTables)
31 CStressTestEngine *self = new (ELeave) CStressTestEngine;
32 CleanupStack::PushL(self);
33 self->ConstructL(aStressTable, aNumTables);
34 CleanupStack::Pop(self);
39 void CStressTestEngine::ConstructL(const TStressTestTable aStressTable[], TUint aNumCases)
41 iStressTable = aStressTable;
42 iNumCases = aNumCases;
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.
50 // Then call the common part with the regular CEglTest_Engine_Local
51 void CStressTestEngine::DoPreambleL()
53 for(TInt curOuterCase = 0; curOuterCase < iNumCases; curOuterCase++)
55 const TTestCaseBase& innerCases = iStressTable[curOuterCase].iTestCaseBase;
56 TPtrC testIds(innerCases.iRelatedTestIds);
57 RegisterTestIdsL(testIds);
63 // Derived function from CEglTest_Engine_Local, so that we can keep the local
65 void CStressTestEngine::DoPostambleL()
67 // Don't loose the verdict.
68 TVerdict v = TestStepResult();
69 CEgltest_Local_Engine::DoPostambleL();
73 CStressTestEngine::CStressTestEngine()
78 CStressTestEngine::~CStressTestEngine()
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
86 void CStressTestEngine::DoModifyL(TInt& aItem)
88 if (aItem & EExpandParamFlag)
90 TInt paramIndex = (aItem & EParamMask) >> EParamShift;
91 if (!iParams[paramIndex])
93 ERR_PRINTF2(_L("Using undefined parameter PARAM%d"), paramIndex);
94 User::Leave(KErrArgument);
96 User::LeaveIfNull(iParams[paramIndex]);
97 aItem &= ERemoveFlagsMask;
98 aItem += iParams[paramIndex]->Value();
103 // Modification of parameters of the testcase entry.
104 void CStressTestEngine::ModifyL(TEngineTestCase &aTestCase)
106 DoModifyL(aTestCase.iEndpointIndex);
107 DoModifyL(aTestCase.iImageIndex);
108 DoModifyL(aTestCase.iArg1);
109 DoModifyL(aTestCase.iArg2);
113 // Move to the next parameter for the parameter set.
114 void CStressTestEngine::NextParams()
116 for(TInt i = 0; i < KMaxParams; i++)
118 // Only update parameters that have been created.
127 // Create parameter set.
128 void CStressTestEngine::CreateParams(const TStressTestSection &aSection)
130 for(TInt i = 0; i < KMaxParams; i++)
132 ENGINE_ASSERT(!iParams[i]);
133 iParams[i] = CStressParam::Factory(aSection.iParams[i]);
138 // Destroy parameter set.
139 void CStressTestEngine::DestroyParams()
141 for(TInt i = 0; i < KMaxParams; i++)
143 // It is harmless to delete a non-existant parameter, so
151 // Set the verdict for this operation on the local exec thread.
152 void CStressTestEngine::UpdateVerdict(TVerdict aVerdict)
154 TRemoteTestParams params;
155 params.iEndpointEngine.iEngineTestCase.iCase = ESetVerdictCase;
156 params.iEndpointEngine.iEngineTestCase.iEndpointIndex = EPass;
158 RunLocalTestCase(params, result);
159 RunRemoteTestCase(ESetVerdictCase, params);
160 SetTestStepResult(aVerdict);
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,
177 TInt &aPreviousCopiesRun)
179 switch(aSection.iErrorPolicy)
181 case EOnErrorPolicyContinue:
182 // Just let it pass...
183 UpdateVerdict(EPass);
185 case EOnErrorPolicyFail:
186 // We should not have errors here.
187 UpdateVerdict(EFail);
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);
203 // The main loop for the test.
204 // Brief pseudo-code:
206 // for each surface_type
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
216 TVerdict CStressTestEngine::doTestStepL()
218 INFO_PRINTF2(_L("Executing test with %d cases..."), iNumCases);
220 for(TInt tests = 0; tests < iNumCases; tests++)
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++)
229 TInt previousCopiesRun = 1;
230 TSurfaceType surfType = tc.iBase.iSurfaceTypeList[surfIter];
232 INFO_PRINTF4(_L("Running testcase GRAPHICS-EGL-%s: %s (surf=%d)"),
233 tc.iBase.iRelatedTestIds, tc.iBase.iName, surfType);
235 TRemoteTestParams configParams = {};
236 configParams.iEndpointEngineConfig.iLogErrors = EFalse;
237 StartRemoteTestStep(configParams);
239 for(TInt curSection = 0; curSection < iStressTable[tests].iNumSections; curSection++)
241 INFO_PRINTF3(_L("Section %d, result=%d"), curSection, TestStepResult());
242 const TStressTestSection §ion = iStressTable[tests].iSections[curSection];
243 CreateParams(section);
244 TInt copies = section.iIterations;
245 if (section.iErrorPolicy == EOnErrorPolicyBreak)
247 if (section.iIterations != 1 && previousCopiesRun == 1)
249 previousCopiesRun = section.iIterations;
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));
257 for(TInt copy = 0; copy < copies; copy++)
259 // Make a copy and put it into the "tc" variable that we set up earlier....
261 for(; section.iEngineTestCase[i].iCase != EFinishedCase; i++)
263 TEngineTestCase ec = section.iEngineTestCase[i];
265 tc.iEngineTestCase[i] = ec;
267 tc.iEngineTestCase[i].iCase = EFinishedCase;
268 TRAPD(err, RunSingleCaseL(tc, surfType));
271 INFO_PRINTF2(_L("RunSingleCaseL left with an error: %d"), err);
273 if (err != KErrNone || TestStepResult() != EPass)
275 if (HandleError(section, copy, copies,
276 curSection, previousCopiesRun))
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);
293 return TestStepResult();
299 // Derived function to start a thread.
300 void CStressTestEngine::StartThreadL(TInt aThreadNumber)
302 const TInt KStackSize = 12000;
303 const TInt KHeapMinSize = 16000;
304 const TInt KHeapMaxSize = 1000000;
306 if (aThreadNumber >= KMaxLoadThreads)
308 User::Panic(_L("StartThreadL"), __LINE__);
311 __e32_atomic_store_rel32(&iStopThreadFlag[aThreadNumber], EFalse);
312 TUint32 random = Math::Random();
314 _LIT(KThreadNameFormat, "%S-%u");
316 // Create a loadthread.
317 _LIT(KThreadName, "EpTestLoadThread");
318 threadName.Format(KThreadNameFormat, &KThreadName, random);
319 TThreadFunction threadFunc = GetThreadFunction(aThreadNumber);
320 if (threadFunc == NULL)
322 ERR_PRINTF2(_L("Requested thread function %d, got NULL pointer back!"), aThreadNumber);
323 User::Leave(KErrArgument);
325 TInt err = iLoadThread[aThreadNumber].Create(threadName, threadFunc,
326 KStackSize, KHeapMinSize, KHeapMaxSize, this, EOwnerThread);
329 ERR_PRINTF2(_L("Could not create load thread - err=%d"), err);
332 iLoadThread[aThreadNumber].Resume();
336 // Terminate a previously started thread.
337 void CStressTestEngine::EndThread(TInt aThreadNumber)
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();
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)
352 ERR_PRINTF2(_L("Should not be called: CStressTestEngine::GetThreadFunction() with %d"), aThreadNumber);
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
363 // Return current value of the parameter. Does not alter the value.
365 // Update the value to the next one. Where relevant, wrap around to the
366 // starting value if the end has been reached.
368 // Factory function to create parameter instances.
369 CStressParam * CStressParam::Factory(const TParamDeclaration &aParamDecl)
372 switch(aParamDecl.iType)
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.
381 case EParamTypeIterator:
382 p = new CStressParamIterator;
385 case EParamTypeTable:
386 p = new CStressParamTable;
389 case EParamTypeRandomizer:
390 p = new CStressParamRandomizer;
394 RDebug::Printf("%s:%d: Type not implemented (type = %d)",
395 __FILE__, __LINE__, aParamDecl.iType);
401 p->Initialize(aParamDecl.iInit, aParamDecl.iEnd, aParamDecl.iStep);
407 CStressParam::~CStressParam()
412 CStressParamIterator::CStressParamIterator()
417 CStressParamIterator::~CStressParamIterator()
422 void CStressParamIterator::Initialize(TInt aInit, TInt aEnd, TInt aStep)
430 void CStressParamIterator::Next()
435 if (iIterator >= iEnd)
442 if (iIterator <= iEnd)
450 TInt CStressParamIterator::Value()
456 CStressParamRandomizer::CStressParamRandomizer()
461 CStressParamRandomizer::~CStressParamRandomizer()
466 void CStressParamRandomizer::Initialize(TInt aMin, TInt aMax, TInt aMul)
471 // Now, pick a new random number.
476 void CStressParamRandomizer::Next()
478 iCurrent = (((TInt)Math::Random()) % ((iMax - iMin) + iMin)) * iMul;
481 TInt CStressParamRandomizer::Value()
487 CStressParamTable::CStressParamTable()
492 CStressParamTable::~CStressParamTable()
497 void CStressParamTable::Initialize(TInt aTable, TInt aCount, TInt /* aUnused */)
499 iTable = reinterpret_cast<TInt *>(aTable);
505 void CStressParamTable::Next()
507 iIndex = (iIndex + 1) % iCount;
511 TInt CStressParamTable::Value()
513 return iTable[iIndex];