graphicstest/graphicstestharness/src/TGraphicsHarness.cpp
changeset 0 5d03bc08d59c
child 103 2717213c588a
--- /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 <apgtask.h>
+#include <hal.h>
+#include <w32debug.h>
+#include <e32std.h> 
+#include <graphics/fbsdefs.h>
+
+#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<TWsDebugHeapInfo> 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) && (currentAttempt<MaxNumberOfAttempt) );
+		}
+	RFbsSession::Disconnect();	
+
+	delete tc;
+
+	__UHEAP_MARKEND;
+	
+	return TestStepResult();
+	}
+
+void CTGraphicsStep::CloseAllPanicWindows(TInt aId, RWsSession& ws) const
+	{
+	TInt idFocus = ws.GetFocusWindowGroup();
+	TWsEvent event;
+	event.SetType(EEventKey); //EEventKeyDown
+	TKeyEvent *keyEvent = event.Key();
+	keyEvent->iCode = 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;
+	}
+