sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @test sl@0: @internalComponent - Internal Symbian test code sl@0: */ sl@0: sl@0: #include "tfbsbase.h" sl@0: #include "fbsmessage.h" sl@0: sl@0: CTFbsBase::CTFbsBase(CTestStep* aStep, TBool aRunWithLowMemory): sl@0: CTGraphicsBase(aStep), sl@0: iTestStep(*aStep), sl@0: iLastTestCase(EFalse), sl@0: iRunWithLowMemory(aRunWithLowMemory) sl@0: { sl@0: } sl@0: sl@0: CTFbsBase::~CTFbsBase() sl@0: { sl@0: } sl@0: sl@0: /** Run the passed the test case. Classes that inherit from CTFbsBase should override this sl@0: and choose which test case to run depending on the passed test case number. Test cases are sl@0: run once normally, 1..n times with out of memory (OOM) testing switched on for the FBServ sl@0: heap and 1..n times with OOM testing switched on for the current heap. sl@0: sl@0: @param aCurTestCase The number of the test case to run sl@0: */ sl@0: void CTFbsBase::RunTestCaseL(TInt aCurTestCase) sl@0: { sl@0: if(iLastTestCase) sl@0: { sl@0: TestComplete(); sl@0: return; sl@0: } sl@0: sl@0: INFO_PRINTF2(_L("***** Starting test case %i *****"), aCurTestCase); sl@0: sl@0: // Run the test normally first sl@0: iCurrentRunIsLowMemory = EFalse; sl@0: TRAPD(err, RunFbsTestL(aCurTestCase)); sl@0: if(KErrNone != err) sl@0: { sl@0: iTestStep.SetTestStepResult(EFail); sl@0: } sl@0: sl@0: #ifndef _DEBUG sl@0: if(iRunWithLowMemory) sl@0: { sl@0: iRunWithLowMemory = EFalse; sl@0: INFO_PRINTF1(_L("WARNING: Can't run out of memory tests under a release build. OOM tests set to run in ini file so turning OOM tests off.")); sl@0: } sl@0: #endif sl@0: sl@0: // Run the test in out of memory conditions, checking both the FBServ heap and the sl@0: // current thread's heap for memory leaks sl@0: if(iRunWithLowMemory) sl@0: { sl@0: iCurrentRunIsLowMemory = ETrue; sl@0: RFbsSession* fbsSession = RFbsSession::GetSession(); sl@0: ASSERT(fbsSession); sl@0: sl@0: INFO_PRINTF2(_L("***** Running Out Of Memory Tests on test case %i (FBSERV heap) *****"), aCurTestCase); sl@0: sl@0: // Save the current state of test step results sl@0: TVerdict currentTestStepResult = iTestStep.TestStepResult(); sl@0: sl@0: // Create 1000 pixel wide bitmap to prevent allocation of scanline buffer sl@0: // during testings, to allow for memory leak testing sl@0: const TSize KSizeInPixels = TSize(1000,1); sl@0: const TDisplayMode KDisplayMode = EColor64K; sl@0: CFbsBitmap* bmp = new(ELeave) CFbsBitmap; sl@0: CleanupStack::PushL(bmp); sl@0: User::LeaveIfError(bmp->Create(KSizeInPixels, KDisplayMode)); sl@0: CleanupStack::PopAndDestroy(bmp); sl@0: sl@0: // Run the test with heap checking for the FbServ heap sl@0: for(TInt failAfter=1; failAfter < 1000; ++failAfter) sl@0: { sl@0: INFO_PRINTF2(_L("***** Set fail after %i allocs (FBSERV heap) *****"), failAfter); sl@0: sl@0: // Count cells so we can know if any leaked sl@0: TInt cellsStart = fbsSession->SendCommand(EFbsMessHeapCount, RFbsSession::EHeapFailTypeHeapMemory); sl@0: fbsSession->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeHeapMemory, failAfter); sl@0: sl@0: // Run test case (implemented by sub class) sl@0: TRAPD(err, RunFbsTestL(aCurTestCase)); sl@0: sl@0: fbsSession->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeHeapMemory); sl@0: TInt cellsEnd = fbsSession->SendCommand(EFbsMessHeapCount, RFbsSession::EHeapFailTypeHeapMemory); sl@0: if(cellsStart < cellsEnd) sl@0: { sl@0: // leaked. sl@0: TInt leakedCells = cellsEnd - cellsStart; sl@0: ERR_PRINTF3(_L("***** On loop number %i we leaked %i cells (FBSERV heap) *****"), failAfter, leakedCells); sl@0: currentTestStepResult = EFail; sl@0: } sl@0: sl@0: // Check to see if any failures reported within test case run sl@0: if(KErrNone == err) sl@0: { sl@0: INFO_PRINTF3(_L("***** Test case %i completed successfully after %d iterations (FBSERV heap) *****"), aCurTestCase, failAfter); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: // Run the test with heap checking for the current thread's heap sl@0: TInt tryCount = 0; sl@0: INFO_PRINTF2(_L("***** Running Out Of Memory Tests on test case %i, current thread's heap (current heap) *****"), aCurTestCase); sl@0: sl@0: FOREVER sl@0: { sl@0: TInt err = KErrNone; sl@0: sl@0: // count cells so we can know how many we leaked sl@0: TInt cellsStart = User::CountAllocCells(); sl@0: ++tryCount; sl@0: INFO_PRINTF2(_L("***** Set fail after %d allocs (current heap) *****"), tryCount); sl@0: sl@0: __UHEAP_FAILNEXT(tryCount); sl@0: __UHEAP_MARK; sl@0: sl@0: TRAP(err, RunFbsTestL(aCurTestCase)); sl@0: sl@0: TBool finishedCorrectly = EFalse; sl@0: if ((err == KErrNone)) sl@0: { sl@0: // claims to have finished correctly, and we're not failing every alloc sl@0: finishedCorrectly = iStep->CheckForHeapFailNext(); sl@0: } sl@0: __UHEAP_RESET; sl@0: TInt cellsEnd = User::CountAllocCells(); sl@0: if (cellsStart < cellsEnd) sl@0: { sl@0: // leaked. sl@0: TInt leakedCells = cellsEnd - cellsStart; sl@0: ERR_PRINTF3(_L("***** On loop number %d we leaked %d cells (current heap). About to cause panic."),tryCount,leakedCells); sl@0: } sl@0: __UHEAP_MARKEND; sl@0: sl@0: // check to see if we finished all OOM testing successfully sl@0: if ((err == KErrNone) && finishedCorrectly) sl@0: { sl@0: INFO_PRINTF3(_L("***** Test case %i completed successfully after %d iterations (current heap) *****"), aCurTestCase, tryCount); sl@0: break; sl@0: } sl@0: sl@0: if (tryCount == 999) sl@0: { sl@0: ERR_PRINTF1(_L("***** OOM testing stopped after 999 iterations (current heap)")); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: // Restore test step result and ignore any test failures the out of memory tests produce sl@0: iTestStep.SetTestStepResult(currentTestStepResult); sl@0: } sl@0: } sl@0: sl@0: /** Helper method for extracting a TRgb colour from the passed buffer given a pixel sl@0: offset in to the buffer and a display mode. sl@0: sl@0: @param aBuffer A buffer to extract the colour from. sl@0: @param aPixelOffset A pixel offset to use in to the buffer. sl@0: @param aDispMode The display mode to use when converting the pixel colour to TRgb. sl@0: */ sl@0: TRgb CTFbsBase::ExtractRgb(TUint8* aBuffer, TInt aPixelOffset, TDisplayMode aDispMode) sl@0: { sl@0: switch (aDispMode) sl@0: { sl@0: case EGray2: sl@0: { sl@0: TUint8 byte = *(aBuffer + (aPixelOffset >> 3)); sl@0: if (byte & (1 << (aPixelOffset & 7))) sl@0: return KRgbWhite; sl@0: return KRgbBlack; sl@0: } sl@0: case EGray4: sl@0: { sl@0: TUint8 byte = *(aBuffer + (aPixelOffset >> 2)); sl@0: byte >>= ((aPixelOffset & 3) << 1); sl@0: return TRgb::Gray4(byte & 3); sl@0: } sl@0: case EGray16: sl@0: { sl@0: TUint8 byte = *(aBuffer + (aPixelOffset >> 1)); sl@0: if (aPixelOffset & 1) sl@0: byte >>= 4; sl@0: return TRgb::Gray16(byte & 0xf); sl@0: } sl@0: case EGray256: sl@0: return TRgb::Gray256(*(aBuffer + aPixelOffset)); sl@0: case EColor16: sl@0: { sl@0: TUint8 byte = *(aBuffer + (aPixelOffset >> 1)); sl@0: if (aPixelOffset & 1) sl@0: byte >>= 4; sl@0: return TRgb::Color16(byte & 0xf); sl@0: } sl@0: case EColor256: sl@0: return TRgb::Color256(*(aBuffer + aPixelOffset)); sl@0: case EColor4K: sl@0: { sl@0: TUint16 doubleByte = *(((TUint16*)aBuffer) + aPixelOffset); sl@0: return TRgb::Color4K(doubleByte & 0xfff); sl@0: } sl@0: case EColor64K: sl@0: { sl@0: TUint16 doubleByte = *(((TUint16*)aBuffer) + aPixelOffset); sl@0: return TRgb::Color64K(doubleByte); sl@0: } sl@0: case EColor16M: sl@0: { sl@0: aBuffer += aPixelOffset * 3; sl@0: TInt value = *aBuffer++; sl@0: value |= *aBuffer++ << 8; sl@0: value |= *aBuffer << 16; sl@0: return TRgb::Color16M(value); sl@0: } sl@0: case ERgb: sl@0: return *(((TRgb*)aBuffer) + aPixelOffset); sl@0: case EColor16MU: sl@0: { sl@0: return TRgb::Color16MU(*(((TUint32*)aBuffer) + aPixelOffset)); sl@0: } sl@0: case EColor16MA: sl@0: { sl@0: return TRgb::Color16MA(*(((TUint32*)aBuffer) + aPixelOffset)); sl@0: } sl@0: case EColor16MAP: sl@0: { sl@0: return TRgb::_Color16MAP(*(((TUint32*)aBuffer) + aPixelOffset)); sl@0: } sl@0: default: sl@0: break; sl@0: }; sl@0: return KRgbBlack; sl@0: } sl@0: sl@0: /** Function to be used by classes that inherit from CTFbsBase. SetLastTestCase() sl@0: should be called after the last test case for a class is called to signal that sl@0: testing has finished for that class. sl@0: */ sl@0: void CTFbsBase::SetLastTestCase() sl@0: { sl@0: iLastTestCase = ETrue; sl@0: }