diff -r 000000000000 -r 5d03bc08d59c graphicstest/graphicstestharness/src/TGraphicsHarness.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicstest/graphicstestharness/src/TGraphicsHarness.cpp Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,633 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include +#include +#include + +#include "TGraphicsHarness.h" +#include "GraphicsTestUtilsServer.h" + +_LIT(KGraphicsTestFrameworkPanic, "Graphics Test Framework"); +const TInt KTestCleanupStack = 0x40; + +const TDisplayMode testDisplayModes[] = + { + EGray2, + EGray4, + EGray16, + EGray256, + EColor16, + EColor256, + EColor64K, + EColor16M, + EColor4K, + EColor16MU, + EColor16MA, + EColor16MAP, + }; + +/** + The test code manager, provides functions to set active object + with lowest priority for running tests in auto mode. + */ +class CTestManager : public CActive + { +friend class CTGraphicsBase; +protected: + static CTestManager* NewL(MTestCases* aAutoTestApp); + ~CTestManager(); + void FinishAllTestCases(); + void StartTest(); //initialize an active object and set it status as active + void SetSelfDrive(TBool aSelfDrive); + void CaseComplete(); +private: + CTestManager(MTestCases* aAutoTestApp); + void NextTest(); + // from CActive + void RunL(); + void DoCancel(); + TInt RunError(TInt aError); +private: + MTestCases* iTestCase; + TInt iCurTestCaseNumber; //a current test case, every time when function RunTestCaseL is called this member inc by one + TBool iTestCompleted; + TBool iSelfDrive; + }; + +/** Construct an active object with the lowest priority */ +CTestManager::CTestManager(MTestCases* aTestCases) : + CActive(EPriorityIdle), iTestCase(aTestCases), iSelfDrive(EFalse) + {} + +CTestManager::~CTestManager() + { + Cancel(); + } + +CTestManager* CTestManager::NewL(MTestCases* aTestCases) + { + CTestManager *theTestManager=new (ELeave) CTestManager(aTestCases); + CActiveScheduler::Add(theTestManager); + return theTestManager; + } + +void CTestManager::RunL() + { + __ASSERT_ALWAYS(iTestCase, User::Panic(KGraphicsTestFrameworkPanic, KErrBadHandle)); + if( iTestCompleted) + { + return; + } + + // debug statement to indicate progress of test suite by + // printing the sub-test that is currently active + TTime timeStamp; + timeStamp.HomeTime(); + TBuf<50> dateStr; + _LIT(KDateString3,"%-B%:0%J%:1%T%:2%S%:3.%Cms"); + timeStamp.FormatL(dateStr, KDateString3); + ++iCurTestCaseNumber; + RDebug::Print(_L("%S - Test Case Number: %d"), &dateStr, iCurTestCaseNumber); + + iTestCase->RunTestCaseL(iCurTestCaseNumber); + if (iTestCompleted) + { + _LIT(KFinished,"Finished test case %d and test completed"); + RDebug::Print(KFinished,iCurTestCaseNumber); + } + else + { + if (iSelfDrive) + { + _LIT(KStarted,"Started test case %d"); + RDebug::Print(KStarted,iCurTestCaseNumber); + } + else + { + NextTest(); + } + } + } + +void CTestManager::DoCancel() + { + if (!iSelfDrive) + iTestCompleted = ETrue; + } + +TInt CTestManager::RunError(TInt aError) + { + TTime timeStamp; + timeStamp.HomeTime(); + TBuf<50> dateStr; + _LIT(KDateString3,"%-B%:0%J%:1%T%:2%S%:3 %Cms"); + timeStamp.FormatL(dateStr, KDateString3); + _LIT(KTestLeft,"RunTestCaseL left of %S - Test Case Number: %d"); + RDebug::Print(KTestLeft, &dateStr, iCurTestCaseNumber); + + aError = iTestCase->RunTestCaseLeft(aError); + FinishAllTestCases(); + return aError; + } + +/** + Initialize an active object and set it as active + */ +void CTestManager::StartTest() + { + TRequestStatus *pS= (&iStatus); + User::RequestComplete(pS, 0); + SetActive(); + } + +/** + Time to move on to the next test step + */ +void CTestManager::NextTest() + { + _LIT(KFinished,"Finished test case %d"); + RDebug::Print(KFinished,iCurTestCaseNumber); + StartTest(); + } + +/** + Stop active scheduler, and quit a test step + */ +void CTestManager::FinishAllTestCases() + { + iTestCompleted = ETrue; + CActiveScheduler::Stop(); + } + +/** + Controls wether the manager calls RunTestCaseL whenever the system is otherwise idol + */ +void CTestManager::SetSelfDrive(TBool aSelfDrive) + { + if (iSelfDrive!=aSelfDrive) + { + iSelfDrive = aSelfDrive; + if (aSelfDrive) + { + if (IsActive()) + Cancel(); + } + else + { + if (!IsActive() && !iTestCompleted) + NextTest(); + } + } + } + +/** + Tells the manager this case is finished so you can call RunTestCaseL again + */ +void CTestManager::CaseComplete() + { + __ASSERT_DEBUG(!IsActive(), User::Panic(KGraphicsTestFrameworkPanic, ETestPanicAlreadyActive)); + if (iSelfDrive && !iTestCompleted) + NextTest(); + } + + +//------------- + +EXPORT_C const TDesC& CTGraphicsBase::ColorModeName(TDisplayMode aMode) + { + _LIT(KNone,"None"); + _LIT(KGray2,"Grey2"); + _LIT(KGray4,"Grey4"); + _LIT(KGray16,"Grey16"); + _LIT(KGray256,"Grey256"); + _LIT(KColor16,"Color16"); + _LIT(KColor256,"Color256"); + _LIT(KColor4K,"Color4K"); + _LIT(KColor64K,"Color64K"); + _LIT(KColor16M,"Color16M"); + _LIT(KColor16MU,"Color16MU"); + _LIT(KColor16MA,"Color16MA"); + _LIT(KColor16MAP,"Color16MAP"); + _LIT(KRgb,"RGB"); + _LIT(KUnknown,"Unknown"); + switch(aMode) + { + case ENone: + return KNone; + case EGray2: + return KGray2; + case EGray4: + return KGray4; + case EGray16: + return KGray16; + case EGray256: + return KGray256; + case EColor16: + return KColor16; + case EColor256: + return KColor256; + case EColor64K: + return KColor64K; + case EColor16M: + return KColor16M; + case ERgb: + return KRgb; + case EColor4K: + return KColor4K; + case EColor16MU: + return KColor16MU; + case EColor16MA: + return KColor16MA; + case EColor16MAP: + return KColor16MAP; + default: + return KUnknown; + } + } + +EXPORT_C const TDesC& CTGraphicsBase::RotationName(CFbsBitGc::TGraphicsOrientation aOrientation) + { + _LIT(K0,"Normal"); + _LIT(K90,"Rotated90"); + _LIT(K180,"Rotated180"); + _LIT(K270,"Rotated270"); + _LIT(KUnknown,"Unknown"); + switch(aOrientation) + { + case CFbsBitGc::EGraphicsOrientationNormal: + return K0; + case CFbsBitGc::EGraphicsOrientationRotated90: + return K90; + case CFbsBitGc::EGraphicsOrientationRotated180: + return K180; + case CFbsBitGc::EGraphicsOrientationRotated270: + return K270; + default: + return KUnknown; + } + } + +EXPORT_C void CTGraphicsBase::SaveScreenShotL(CFbsScreenDevice* aScdv) + { +#ifdef __WINS__ + _LIT(KBitmapDrive, "c:"); +#else + _LIT(KBitmapDrive, "e:"); +#endif + _LIT(KBitmapPath, "\\screenshot.mbm"); + TDisplayMode dispMode = aScdv->DisplayMode(); + TSize scrSize = aScdv->SizeInPixels(); + CFbsBitmap* dstBmp = new(ELeave) CFbsBitmap; + CleanupStack::PushL(dstBmp); + User::LeaveIfError(dstBmp->Create(scrSize, dispMode)); + HBufC8* row = HBufC8::NewLC(scrSize.iWidth*4); + TPtr8 prow = row->Des(); + for (TInt ii = 0; ii < scrSize.iHeight; ++ii) + { + aScdv->GetScanLine(prow, TPoint(0, ii), scrSize.iWidth, dispMode); + dstBmp->SetScanLine(prow,ii); + } + CleanupStack::PopAndDestroy(row); + TFileName mbmFile; + mbmFile.Append(KBitmapDrive); + mbmFile.Append(KBitmapPath); + User::LeaveIfError(dstBmp->Save(mbmFile)); + CleanupStack::PopAndDestroy(dstBmp); + } + +EXPORT_C CTGraphicsBase::CTGraphicsBase(CTestStep* aStep) : + iStep(aStep) + {} + +EXPORT_C CTGraphicsBase::~CTGraphicsBase() + { + if(iTestManager) + { + iTestManager -> Cancel(); + } + delete iTestManager; + } + +void CTGraphicsBase::InitializeL() + { + __ASSERT_DEBUG(iStep, User::Panic(KGraphicsTestFrameworkPanic, KErrBadHandle)); + iTestManager = CTestManager::NewL(this); + } + +/** + The function must be called after all test cases completed + */ +EXPORT_C void CTGraphicsBase::TestComplete() + { + if(iTestManager) + { + iTestManager -> FinishAllTestCases(); + } + } + +EXPORT_C void CTGraphicsBase::SetSelfDrive(TBool aSelfDrive) + { + if (iTestManager) + iTestManager->SetSelfDrive(aSelfDrive); + } + +EXPORT_C void CTGraphicsBase::CaseComplete() + { + if (iTestManager) + iTestManager->CaseComplete(); + } + +EXPORT_C TInt CTGraphicsBase::RunTestCaseLeft(TInt aError) + { + _LIT(KRunTestCaseLLeft,"The RunTestCaseL left with %d"); + ERR_PRINTF2(KRunTestCaseLLeft,aError); + iStep->SetTestStepResult(EFail); + return KErrNone; + } + +/** Start a test cases loop */ +void CTGraphicsBase::Execute() + { + __ASSERT_DEBUG(iTestManager, User::Panic(KGraphicsTestFrameworkPanic, KErrBadHandle)); + __ASSERT_DEBUG(CActiveScheduler::Current(), User::Panic(KGraphicsTestFrameworkPanic, KErrBadHandle)); + + iTestManager -> StartTest(); + CActiveScheduler::Start(); + } +/** + Reset test cases counter to a new value. Can be used for running the same consequence of test + cases with different initial parameters. + aNewCurrentTestCase cannot be negative. +*/ +EXPORT_C void CTGraphicsBase::ResetCounter(TInt aNewCurrentTestCase ) + { + __ASSERT_DEBUG(aNewCurrentTestCase >= 0, User::Panic(KGraphicsTestFrameworkPanic, KErrArgument)); + iTestManager->iCurTestCaseNumber = aNewCurrentTestCase; + } + +//--------------------- +/** + Initialise the cleanup stack. +*/ +void CTGraphicsStep::SetupCleanup(CTrapCleanup*& tc) + { + tc = CTrapCleanup::New(); + if (!tc) + { + User::Panic(_L("Out of memory"), KErrNoMemory); + } + + TRAPD(r, + { + for ( TInt ii = KTestCleanupStack; ii > 0; ii-- ) + CleanupStack::PushL( (TAny*)1 ); + TEST( r == KErrNone ); + CleanupStack::Pop( KTestCleanupStack ); + } ); + } + +void CTGraphicsStep::LogHeapInfo(RWsSession& aWs, TBool aStart) + { + _LIT(KInfoStart,"Start"); + _LIT(KInfoEnd,"End"); + _LIT(KInfoCheckPassed,"WsHeap leak check passed"); + _LIT(KInfoCheckFailed,"Memory leak detected. Number of orphaned cells=%d."); + _LIT(KInfoCheckFailed2,"See epocwindout for the address of the first orphaned cell."); + _LIT(KInfoHeapSummary," WsHeap - Count=%d,Total=%d,Free=%d,Max free=%d"); + _LIT(KInfoDisabled,"Memory leak testing has not been enabled."); + + TPckgBuf heapInfo; + aWs.DebugInfo(EWsDebugInfoHeap,heapInfo); + TBuf<256> infoBuf; + if (aStart) + { + infoBuf.Append(KInfoStart); + } + else + { + infoBuf.Append(KInfoEnd); + TInt heapFailCount=aWs.DebugInfo(EWsDebugFetchCheckHeapResult); + if (heapFailCount==KErrNone) + { + INFO_PRINTF1(KInfoCheckPassed); + } + else if (heapFailCount>0) // Negative error should be ignored as it means the check has not been enabled + { + TEST(0); + ERR_PRINTF2(KInfoCheckFailed,heapFailCount); + ERR_PRINTF1(KInfoCheckFailed2); + } + else + { + WARN_PRINTF1(KInfoDisabled); + } + } + infoBuf.AppendFormat(KInfoHeapSummary,heapInfo().iCount,heapInfo().iTotal,heapInfo().iAvailable,heapInfo().iLargestAvailable); + INFO_PRINTF1(infoBuf); + } + +/** + Main entry point from CTestStep class. + Creates cleanup stack, background window and launches a test +*/ +EXPORT_C TVerdict CTGraphicsStep::doTestStepL() + { + TInt memFree; + HAL::Get(HALData::EMemoryRAMFree, memFree); + INFO_PRINTF2(_L("Test started - RAM free: %d"), memFree); + + __UHEAP_MARK; + CTrapCleanup* tc = NULL; + SetupCleanup(tc); + + TInt err = RFbsSession::Connect(); + if(err != KErrNone) + { + FbsStartup(); + err = RFbsSession::Connect(); + + if(err != KErrNone) + { + User::Panic(_L("Font bitmap session connect"), err); + } + } + RWsSession ws; + err = ws.Connect(); + if (iLogHeapInfo && err==KErrNone) + { + ws.DebugInfo(EWsDebugSetCheckHeapOnDisconnectClient); + LogHeapInfo(ws,ETrue); + } + TInt theId1 = NULL; +#ifdef __WINS__ + RWindowGroup winGroup = RWindowGroup(ws); + RWindow theWindow(ws); + if (err==KErrNone) + { + const TUint32 ENullWsHandle = 0xFFFFFFFF; // Events delivered to this handle are thrown away + //creat background window with the size of the screen + //it is particulary important for tests which draw on the screen, read screen buffer + //and compare result. By default top TEF window is concole and blinking cursor can interfere + //with the work of the tests + TSize size(640, 240); //some default value + //retrieve screen size + err = GetScreenSize(size); + if(err) + { + WARN_PRINTF2(_L("Can't retrieve size from screen driver err = %d"), err); + } + + winGroup.Construct(ENullWsHandle); + winGroup.AutoForeground(ETrue); + theId1 = winGroup.Identifier(); + + theWindow.Construct(winGroup, ENullWsHandle); + theWindow.SetExtent(TPoint(0, 0), size); + theWindow.SetVisible(ETrue); + theWindow.Activate(); + + //the following trick we need to put the window on the top + TApaTaskList taskList(ws); + TApaTask task = taskList.FindByPos(1); + task.BringToForeground(); + TApaTask task1(ws); + task1.SetWgId(theId1); + task1.BringToForeground(); + } +#endif + if (err==KErrNone) + { + CloseAllPanicWindows(theId1, ws); + } + + // initialize the test and kick off the test cases loop + TRAP(err, TestSetupL(); // initialize a test step + ExecuteL()); // run active scheduler, in order to complete test execution + // CTGraphicsStep::TestComplete function needs to be called + + if (err) + { + SetTestStepResult(EFail); + } + + TestClose(); // free all allocated resources here + + if (ws.Handle()) + { + CloseAllPanicWindows(theId1, ws); +#ifdef __WINS__ + theWindow.Close(); + winGroup.Close(); +#endif + ws.Close(); + User::After(50000); + // Prev close will trigger Wserv dummy shutdown and heap check + // We then re-connect to get the result of the shutdown. + RWsSession ws2; + TInt errConnection; + TInt MaxNumberOfAttempt=10; + TInt currentAttempt=0; + do + { + errConnection=ws2.Connect(); + if (errConnection==KErrNone) + { + LogHeapInfo(ws2,EFalse); + ws2.Close(); + } + else + { + RDebug::Printf("Connection Error with Wserv... %i",errConnection); + User::After(50000); + } + currentAttempt++; + }while( (errConnection!=KErrNone) && (currentAttemptiCode = EKeyEscape; + keyEvent->iScanCode = EStdKeyEscape; + keyEvent->iModifiers = 0; + TInt theLimit = 50; + while(idFocus != aId && (theLimit-- > 0)) + { + ws.SendEventToAllWindowGroups(event); + idFocus = ws.GetFocusWindowGroup(); + } + } + +TInt CTGraphicsStep::GetScreenSize(TSize& aSize) const + { + CFbsScreenDevice* dev = NULL; + + TInt err = KErrNone; + TInt sizeOfDisplayMode = sizeof (testDisplayModes) / sizeof(testDisplayModes[0]); + + for(TInt theScreenModeIndex = sizeOfDisplayMode - 1; theScreenModeIndex ; theScreenModeIndex--) + { + TDisplayMode disp = testDisplayModes[theScreenModeIndex]; + TRAP(err, dev = CFbsScreenDevice::NewL(_L(""), disp)); //scdv + if(err == KErrNone) + { + aSize = dev->SizeInPixels(); + delete dev; + return KErrNone; + } + delete dev; + dev = NULL; + } + + return err; + } + +/** Installs an active scheduler and launches a test*/ +void CTGraphicsStep::ExecuteL() + { + CActiveScheduler* theAs = new (ELeave) CActiveScheduler; + CleanupStack::PushL(theAs); + CActiveScheduler::Install(theAs); + + CTGraphicsBase* autoTest = CreateTestL(); + User::LeaveIfNull(autoTest); + CleanupStack::PushL(autoTest); + + autoTest -> InitializeL(); + autoTest -> ConstructL(); + autoTest -> Execute(); + + CleanupStack::PopAndDestroy(2, theAs); + } + +TInt E32Dll( ) + { + return 0; + } +