windowing/windowserver/tauto/TWSGRAPHS.CPP
author Faisal Memon <faisal.memon@nokia.com>
Mon, 19 Jul 2010 13:28:19 +0100
branchNewGraphicsArchitecture
changeset 120 f528087f811a
parent 0 5d03bc08d59c
permissions -rw-r--r--
Update deployment diagram to show guest instead of platsim

// Copyright (c) 2006-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:
// This test step contains a series of tests cases to validate the correct behaviour of PREQ1246 implementation.
// In order to create these test cases, basic implementations of the objects involved in this PREQ will be created,
// .i.e. CWsGraphic-derived objects (generically named CWsGraphicTest) and CWsGraphicDrawer-derived objects
// (generically named CWsGraphicDrawerTest).
// Actual construction is performed by a UI-specific entity such as a theme manager. The test code shall replace
// that theme manager functionality, in terms of being the test code who owns a collection of CWsGraphicTest
// objects.
// 
//

/**
 @file
 @test
 @internalComponent - Internal Symbian test code
*/

#include "TWSGRAPHS.H"
#include "../inc/WSGRAPHICDRAWERARRAY.H"
#include "../../nga/graphicdrawer/panics.h"
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA
#include "wsbufferdrawer.h"
#endif

_LIT(KTestExe, "TWSGRAPHICTEST.exe");
_LIT(KSpace, " ");

#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
const TInt KCustomTextCursorId = TTextCursor::ETypeLastBasic + 57; // 57 is arbitrary
#endif

CCrWin* CCrWin::NewL(TInt aScreenId, TBool aDraw)
	{
	CCrWin* win = new(ELeave) CCrWin;
	CleanupStack::PushL(win);
	win->ConstructL(aScreenId, aDraw);
	CleanupStack::Pop(win);
	return win;
	}

CCrWin::~CCrWin()
	{
	iWin.Close();
	iGroup.Close();
	delete iGc;
	delete iScr;
	iWs.Close();
	}

void CCrWin::ConstructL(TInt aScreenId, TBool aDraw)
	{
	User::LeaveIfError(iWs.Connect());
	iScr = new(ELeave) CWsScreenDevice(iWs);
	User::LeaveIfError(iScr->Construct(aScreenId));
	User::LeaveIfError(iScr->CreateContext(iGc));
	iGroup = RWindowGroup(iWs);
	User::LeaveIfError(iGroup.Construct(0xbadbabe,ETrue));
	iGroup.SetOrdinalPosition(0,100);
	iWin = RWindow(iWs);
	User::LeaveIfError(iWin.Construct(iGroup,0xbadcafe));
	iWin.SetRequiredDisplayMode(EColor64K);
	iWin.Activate();
	iWs.Flush();
	if (aDraw)
	Draw();
	}

void CCrWin::Draw()
	{
	iWin.BeginRedraw();
	iGc->Activate(iWin);
	iGc->SetBrushColor(KRgbRed);
	iGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	TRect rect(iScr->SizeInPixels());
	iGc->DrawRect(rect);
	iGc->SetBrushColor(KRgbBlue);
	iGc->DrawEllipse(TRect(rect.iTl.iX,rect.iTl.iY,rect.iBr.iX/2,rect.iBr.iY));
	iGc->DrawEllipse(TRect(rect.iBr.iX/2,rect.iTl.iY,rect.iBr.iX,rect.iBr.iY));
	iGc->Deactivate();
	iWin.EndRedraw();
	iWs.Flush();
	}


void CCrWin::DrawFirstHalf()
	{
	iWin.BeginRedraw();
	iGc->Activate(iWin);
	iGc->SetBrushColor(KRgbRed);
	iGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	TRect rect(TPoint(0,0),TSize(iScr->SizeInPixels().iWidth/2,iScr->SizeInPixels().iHeight));
	iGc->DrawRect(rect);
	iWs.Flush();	
	}

void CCrWin::DrawSecondHalf()
	{
	TRect rect(TPoint(iScr->SizeInPixels().iWidth/2,0),TSize(iScr->SizeInPixels().iWidth/2,iScr->SizeInPixels().iHeight));
	iGc->DrawRect(rect);
	iGc->Deactivate();
	iWin.EndRedraw();	
	iWs.Flush();		
	}

/** 
The objective of this function is, two animations should run independently
with respective frame rate in the given time interval.
The time delay allows to draw animations freely and the plug-in
calculates number of times DoDraw() function called during this interval.

@param TInt Wsgrphic test plug-in id.
*/
void CCrWin::DrawGraphic(TInt aWsId)
	{
	// draw the animation in two positions
	const TSize screenSize = iScr->SizeInPixels();	
	const TRect position(0,0,screenSize.iWidth/2,screenSize.iHeight);
	const TRect position2((screenSize.iWidth/2)+1,0,screenSize.iWidth,screenSize.iHeight);
	//PeterI if CWsGraphic animation areas overlap then when one redraws the other will as well.
	//2 separate positions are needed otherwise the framerates will be identical.
	
	iWin.BeginRedraw();
	iGc->Activate(iWin);
	const TUint8 animid1=0;
	const TUint8 fps1=20;
	TBuf8<2> animData1;
	animData1.Append(animid1);   //animId1
	animData1.Append(fps1); //20fps
	iGc->DrawWsGraphic(aWsId,position,animData1);
	iWs.Flush();
	User::After(200000);
	const TUint8 animid2=1;
	const TUint8 fps2=60;
	TBuf8<2> animData2;
	animData2.Append(animid2);   //animId2
	animData2.Append(fps2); //60fps
	iGc->DrawWsGraphic(aWsId,position2,animData2);
	iWs.Flush();
	User::After(200000);
	iGc->Deactivate();
	iWin.EndRedraw();
	iWs.Flush();
	}

/**
 * Set a standard text cursor on this window.
 * @see RWindowGroup::SetTextCursor()
 */
void CCrWin::SetTextCursor(const TPoint &aPos, const TTextCursor &aCursor)
	{
	iGroup.SetTextCursor(iWin, aPos, aCursor);
	}

/**
 * Cancel a text cursor from this window.
 * @see RWindowGroup::CancelTextCursor()
 */
void CCrWin::CancelTextCursor()
	{
	iGroup.CancelTextCursor();
	}

CCrAlphaWin* CCrAlphaWin::NewL(TInt aScreenId)
	{
	CCrAlphaWin* win = new(ELeave) CCrAlphaWin;
	CleanupStack::PushL(win);
	win->ConstructL(aScreenId);
	CleanupStack::Pop(win);
	return win;
	}

CCrAlphaWin::~CCrAlphaWin()
	{
	iWin.Close();
	iGroup.Close();
	delete iScr;
	iWs.Close();
	}

void CCrAlphaWin::ConstructL(TInt aScreenId)
	{
	User::LeaveIfError(iWs.Connect());
	iScr = new(ELeave) CWsScreenDevice(iWs);
	User::LeaveIfError(iScr->Construct(aScreenId));
	iGroup = RWindowGroup(iWs);
	User::LeaveIfError(iGroup.Construct(0xbadc0de,ETrue));
	iGroup.SetOrdinalPosition(0,100);
	iWin = RWindow(iWs);
	User::LeaveIfError(iWin.Construct(iGroup,0xbadbeef));
	iWin.SetRequiredDisplayMode(EColor64K);
	iWin.SetTransparencyAlphaChannel();
	iWin.SetBackgroundColor(TRgb(0xff,0xff,0,0x80));
	iWin.Activate();
	iWs.Flush();
	}


//
//  CTWsGraphs
//

CTWsGraphs::CTWsGraphs(CTestStep* aStep):
	CTWsGraphicsBase(aStep)
	{
	}

#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
LOCAL_D void DeleteSpriteMember(TAny* aSpriteMember)
	{
	TSpriteMember* member=reinterpret_cast<TSpriteMember*>(aSpriteMember);
	delete member->iBitmap;
	member->iBitmap=NULL;
	delete member->iMaskBitmap;
	member->iMaskBitmap=NULL;
	}
#endif

CTWsGraphs::~CTWsGraphs()
	{
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
	DeleteSpriteMember(&iSpriteMemberArray[0]);
	iSpriteMemberArray.Close();
#endif
	delete iGdCoverage;
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
	delete iAfter;
	delete iBefore;
	delete iBackCopy;
	delete iFrontCopy;
#endif
	delete iListen;
	delete iNotify2;
	delete iNotify1;
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
	delete iRedir;
#endif
	}

void CTWsGraphs::ConstructL()
	{
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
	iRedir = CWsRedir::NewL(iTest->iScreenNumber,ETrue);
	iRedir->SetCallBack(TCallBack(CTWsGraphs::PluginCallBack,this));
#endif
	iNotify1 = CWsNotify::NewL(EFalse);
	iNotify2 = CWsNotify::NewL(ETrue);
	iListen = CWsListen::NewL(ETrue);
	iListen->SetCallBack(TCallBack(CTWsGraphs::PluginCallBack,this));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
	iFrontCopy = new(ELeave) CFbsBitmap;
	iBackCopy = new(ELeave) CFbsBitmap;
	iBefore = new(ELeave) CFbsBitmap;
	User::LeaveIfError(iBefore->Create(TheClient->iScreen->SizeInPixels(), EColor64K));
	iAfter = new(ELeave) CFbsBitmap;
	User::LeaveIfError(iAfter->Create(TheClient->iScreen->SizeInPixels(), EColor64K));
#endif
	iGdCoverage = CWsGdCoverage::NewL();
	iGdCoverage->SetCallBack(TCallBack(CTWsGraphs::PluginCallBack,this));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
	TSpriteMember spriteMember;
	spriteMember.iBitmap = NULL;
	spriteMember.iMaskBitmap = NULL;
	spriteMember.iInvertMask =EFalse;
	spriteMember.iDrawMode = CGraphicsContext::EDrawModePEN;
	spriteMember.iOffset = TPoint();
	spriteMember.iInterval = TTimeIntervalMicroSeconds32(0);
	CleanupStack::PushL(TCleanupItem(DeleteSpriteMember, &spriteMember));
	spriteMember.iBitmap = new (ELeave) CFbsBitmap;
	User::LeaveIfError(spriteMember.iBitmap->Load(TEST_BITMAP_NAME, EMbmWsautotestBmp1));
	spriteMember.iMaskBitmap = new (ELeave) CFbsBitmap;
	User::LeaveIfError(spriteMember.iMaskBitmap->Load(TEST_BITMAP_NAME, EMbmWsautotestBmp1mask));
	User::LeaveIfError(iSpriteMemberArray.Append(spriteMember));
	CleanupStack::Pop(&spriteMember);
#endif
	}

void CTWsGraphs::LaunchNewProcess(const TDesC& aExecutable)
	{
	TBuf<128> args;
 	args.Append(KSpace);
	args.AppendNum(iTest->iScreenNumber);
	RProcess pr;
	TInt err = pr.Create(aExecutable,args);
	if (err == KErrNone)
		{
		TRequestStatus status;
		pr.Logon(status);
		pr.Resume();
		User::WaitForRequest(status);
		err = pr.ExitReason();
		pr.Close();
		if (err != KErrNone)
			{
			_LIT(KLog,"%S returned error: %d. Check RDebug output.");
			LOG_MESSAGE3(KLog, &aExecutable, err);
			}
		}
	else
		{
		_LIT(KLog,"Can't create the process (%S), err=%d");
		LOG_MESSAGE3(KLog, &aExecutable, err);
		}
	TEST(err == KErrNone);
	// Restore main test group to foreground.
	TheClient->iGroup->GroupWin()->SetOrdinalPosition(0);
	}

TInt CTWsGraphs::PluginCallBack(TAny* /*aArg*/)
	{
	return (TInt)EWait;
	}

#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA

/**
 @SYMTestCaseID				GRAPHICS-WSERV-0371
 @SYMREQ					GT247-CR0714
 @SYMTestCaseDesc			Test interface extension
 @SYMTestPriority			High
 @SYMTestStatus				Implemented
 @SYMTestActions			Retrieves object interfaces from Content Rendering Plugin (plugin).
							Actions step:
							-Create plugin
							-Query interfaces obtained from plugin side
 @SYMTestExpectedResults	Supported interfaces should return non null
*/
TestState CTWsGraphs::TestInterfaceExtensionL()
	{
	if (iSubState==0)
		{
		_LIT(KTestInterfaceExtension, "TestInterfaceExtension");
		INFO_PRINTF1(KTestInterfaceExtension);

		++iSubState;
		Mem::FillZ(&iRedirInfo, sizeof(TRedirectorInfo));
		iRedir->QueryPlugin(iRedirInfo);
		return EWait;
		}
	TEST(iRedirInfo.iScreenConfigInterface!=NULL);
	TEST(iRedirInfo.iFrontBufferInterface!=NULL);
	TEST(iRedirInfo.iScreenBitmapHandle!=0);
	iFrontCopy->Duplicate(iRedirInfo.iScreenBitmapHandle);

	if (TransparencySupportedL()!=KErrNotSupported)
		{
		TEST(iRedirInfo.iBackBufferInterface!=NULL);
		TEST(iRedirInfo.iFlickerBitmapHandle!=0);
		iBackCopy->Duplicate(iRedirInfo.iFlickerBitmapHandle);
		}

	++(iTest->iState);
	iSubState = 0;
	return ENext;
	}

#endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA

void CTWsGraphs::CreateWindowL(TBool aDraw)
	{
	iWin = CCrWin::NewL(iTest->iScreenNumber, aDraw);
	}

void CTWsGraphs::DestroyWindowL()
	{
	delete iWin;
	iWin = NULL;
	}

void CTWsGraphs::CreateAlphaWindowL()
	{
	iAlpha = CCrAlphaWin::NewL(iTest->iScreenNumber);
	}

void CTWsGraphs::DestroyAlphaWindowL()
	{
	delete iAlpha;
	iAlpha = NULL;
	}

TBool CTWsGraphs::CompareBitmapArea16Bpp(CFbsBitmap* aBmp1, const TPoint& aPos1, CFbsBitmap* aBmp2, const TPoint& aPos2, const TSize& aSize)
	{
	const TDisplayMode dispmode = aBmp1->DisplayMode();
	if (dispmode!=aBmp2->DisplayMode())
		return EFalse;
	const TInt stride1 = aBmp1->DataStride();
	const TInt stride2 = aBmp2->DataStride();
	const TInt linebytes = aSize.iWidth * 2;
	const TInt pixelbytes = 2;
	aBmp1->LockHeap();
	const TUint8* p1 = ((const TUint8*)aBmp1->DataAddress())+aPos1.iY*stride1+aPos1.iX*pixelbytes;
	const TUint8* p2 = ((const TUint8*)aBmp2->DataAddress())+aPos2.iY*stride2+aPos2.iX*pixelbytes;
	for (TInt y=0; y<aSize.iHeight; ++y)
		{
		if (Mem::Compare(p1+y*stride1,linebytes,p2+y*stride2,linebytes)!=0)
			{
			aBmp1->UnlockHeap();
			return EFalse;
			}
		}
	aBmp1->UnlockHeap();
	return ETrue;
	}

#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
TestState CTWsGraphs::TestScreenRedirectionL()
	{
	if (iSubState==0)
		{
		_LIT(KTestScreenRedirection, "TestScreenRedirection");
		INFO_PRINTF1(KTestScreenRedirection);

		++iSubState;
		/**
		 @SYMTestCaseID				GRAPHICS-WSERV-0372
		 @SYMREQ					GT247-CR0714
		 @SYMTestCaseDesc			Redirect wserv screen drawing to custom graphics context
		 @SYMTestPriority			High
		 @SYMTestStatus				Implemented
		 @SYMTestActions			Redirects wserv screen drawing to bitmap context owned by plugin.
									Actions step:
									-Draw opaque window.
									-Save screen content to a bitmap
									-Instruct plugin to redirect wserv screen drawing to a bitmap device
									-Draw the same window again
									-Retrieve plugin bitmap and compare against  the saved bitmap
		 @SYMTestExpectedResults	Bitmap content match
		*/
		CreateWindowL();		
		TheClient->iScreen->CopyScreenToBitmap(iBefore);
		DestroyWindowL();
		iRedir->Redirect(CWsRedir::EFrontBuffer, ETrue);
		return EWait;
		}

	if (iSubState==1)
		{
		++iSubState;
		CreateWindowL();
		TSize sz = iBefore->SizeInPixels();
		TInt bytes = sz.iWidth*sz.iHeight*2; // EColor64K
		iBefore->LockHeap();
		TEST(Mem::Compare((const TUint8*)iFrontCopy->DataAddress(),bytes,(const TUint8*)iBefore->DataAddress(),bytes)==0);
		iBefore->UnlockHeap();

		Mem::FillZ(&iRedirInfo, sizeof(TRedirectorInfo));			
		iRedir->QueryPlugin(iRedirInfo);
		return EWait;
		}

	if (iSubState==2)
		{
		++iSubState;
		/**
		 @SYMTestCaseID				GRAPHICS-WSERV-0047
		 @SYMTestCaseDesc			Screen update event
		 @SYMTestPriority			Medium
		 @SYMTestStatus				Implemented
		 @SYMTestActions			Check plugin receive screen update event during redirection
		 @SYMTestExpectedResults	Counter is non-zero
		*/
		TEST(iRedirInfo.iUpdateCounter>0);

		DestroyWindowL();
		/**
		 @SYMTestCaseID				GRAPHICS-WSERV-0373
		 @SYMREQ					GT247-CR0714
		 @SYMTestCaseDesc			Stop wserv screen drawing redirection
		 @SYMTestPriority			High
		 @SYMTestStatus				Implemented
		 @SYMTestActions			Stop wserv screen drawing redirection.
									Actions step:
									-Instruct plugin to stop wserv screen drawing redirection
									-Draw the same window again
									-Save screen content to another bitmap
									-Compare the saved bitmap against newly saved bitmap
		 @SYMTestExpectedResults	Bitmap content match
		*/
		iRedir->Redirect(CWsRedir::EFrontBuffer, EFalse);
		return EWait;
		}

	if (iSubState==3)
		{
		++iSubState;
		CreateWindowL();
		TheClient->iScreen->CopyScreenToBitmap(iAfter);
		TSize sz = iBefore->SizeInPixels();	
		TInt bytes = sz.iWidth*sz.iHeight*2; // EColor64K	
		iAfter->LockHeap();
		TEST(Mem::Compare((const TUint8*)iAfter->DataAddress(),bytes,(const TUint8*)iBefore->DataAddress(),bytes)==0);
		iAfter->UnlockHeap();
		DestroyWindowL();

		Mem::FillZ(&iRedirInfo, sizeof(TRedirectorInfo));			
		iRedir->QueryPlugin(iRedirInfo);
		return EWait;
		}

	/**
	 @SYMTestCaseID				GRAPHICS-WSERV-0374
	 @SYMTestCaseDesc			Screen update event
	 @SYMTestPriority			Medium
	 @SYMTestStatus				Implemented
	 @SYMTestActions			Check plugin receive no screen update event when redirection is terminated
	 @SYMTestExpectedResults	Counter is zero
	*/
	TEST(iRedirInfo.iUpdateCounter==0);

	++(iTest->iState);
	iSubState = 0;

	return ENext;
	}

TestState CTWsGraphs::TestTextCursorUnderRedirectionL(TTestCursorType aCursorType)
	{
	/**
	 @SYMTestCaseID				GRAPHICS-WSERV-0363
	 @SYMTestCaseDesc			Text Cursor when drawing redirected
	 @SYMTestPriority			Medium
	 @SYMTestStatus				Implemented
	 @SYMTestActions			Action steps:
	 							- Draw the text cursor in the left side of the screen
	 							- Re-direct the Front Buffer
	 							- Move the text cursor to the right side of the screen
	 							- Pause 0.5 seconds because this amount of time is needed
								  to change from the flash ON phase to the flash OFF phase
	 							- Stop re-directing
	 							- See if when we exit re-direction in a different place in
	 							  the phase of the text cursor flashing, whether we get
	 							  non-text cursor drawing artefacts in the old location
	 							  where the text cursor used to be
	 @SYMTestExpectedResults	Left side of the screen does not show a Text Cursor
	 */
	
	ASSERT(aCursorType == ETestStandardTextCursor || aCursorType == ETestCustomTextCursor);
	
	// Cursor Flash Period is 1 second (comprising two phases; ON and OFF)
	const TInt KCursorFlashPeriod = 1000000;
	const TInt KWaitForNextFlashPhase = KCursorFlashPeriod / 2;
	
	// Size of the cursor; it may be either a standard or custom text cursor
	TSize cursorSize = (aCursorType == ETestStandardTextCursor) ? TSize(15, 20) : TSize(80, 80);
		
	// Original Text Cursor position in the left part of the screen
	const TPoint originalCursorPos(45, 40);
	
	// New Text Cursor position in the right half of the screen
	const TPoint newCursorPos((TheClient->iScreen->SizeInPixels().iWidth/2) + 45, 40);
	
	// Clean area of the screen which never had a text cursor
	const TPoint cleanReferencePos(45, 40 + 80);
	
	/* Initial setup to get a window with a standard flashing text cursor */
	if (iSubState == 0)
		{
		++iSubState;			
		CreateWindowL(ETrue);
		
		if (aCursorType == ETestStandardTextCursor)
			{
			_LIT(KTestTextCursorUnderRedirection, "TestTextCursorUnderRedirection(Standard Cursor)");
			INFO_PRINTF1(KTestTextCursorUnderRedirection);	
			iTextCursor.iType=TTextCursor::ETypeRectangle;
			iTextCursor.iHeight=cursorSize.iHeight;
			iTextCursor.iAscent=0;
			iTextCursor.iWidth=cursorSize.iWidth;
			iTextCursor.iFlags=0; 			// means flash the cursor
			iTextCursor.iColor=KRgbGreen;
			iWin->SetTextCursor(originalCursorPos, iTextCursor);
			}
		else if (aCursorType == ETestCustomTextCursor)
			{
			_LIT(KTestTextCursorUnderRedirection, "TestTextCursorUnderRedirection(Custom Cursor)");
			INFO_PRINTF1(KTestTextCursorUnderRedirection);	

			TInt err = TheClient->iWs.SetCustomTextCursor(
					KCustomTextCursorId,
					iSpriteMemberArray.Array(),
					ESpriteFlash,
					RWsSession::ECustomTextCursorAlignTop
					);
			iTextCursor.iType=KCustomTextCursorId;
			iTextCursor.iHeight=cursorSize.iHeight;
			iTextCursor.iAscent=0;
			iTextCursor.iWidth=cursorSize.iWidth;
			iTextCursor.iFlags=TTextCursor::EFlagClipHorizontal; // means flash the cursor and clip the sprite
			iTextCursor.iColor=KRgbCyan;
			iWin->SetTextCursor(originalCursorPos, iTextCursor);
			}
		else
			{
			// unknown type of test being requested
			ASSERT(0);
			}
		iWin->DrawFirstHalf();	
		return EWait;
		}
	/*
	 * Re-direct drawing to another Front Buffer.  Whilst re-directed, change the
	 * position of the text cursor.  Then pause 0.5 seconds because this is how
	 * long it will take to enter the next phase in the flashing cycle.  Finally
	 * stop re-directing.  We exit the re-direction in a different point in the
	 * phase of the text cursor from when we entered it.
	 * This is key to testing for faulty behaviour.
	 */
	if (iSubState==1)
		{
		++iSubState;
		User::After(KCursorFlashPeriod * 2);  // so its easy to visually review progress
		iRedir->Redirect(CWsRedir::EFrontBuffer, ETrue);
		iWin->SetTextCursor(newCursorPos, iTextCursor);
		User::After(KWaitForNextFlashPhase);
		iRedir->Redirect(CWsRedir::EFrontBuffer, EFalse);
		return EWait;
		}
	/*
	 * Paint the right hand side of the screen which should now have a text cursor.
	 */
	if (iSubState==2)
		{
		++iSubState;
		iWin->DrawSecondHalf();
		return EWait;
		}
	/*
	 * Let the cursor flash a few times, as it assists manual viewing of the progress
	 * of the test.
	 */
	if (iSubState==3)
		{
		++iSubState;
		User::After(KCursorFlashPeriod * 3);
		return EWait;
		}
	/*
	 * Check to see if the text cursor did move to the right of the screen.
	 */
	if (iSubState==4)
		{
		++iSubState;
		
		/* When we do a screen comparison, we supply flag 0, which means
		 * don't include the text cursor.  We do this because we are interested
		 * in screen artefacts.
		 */
		TEST(TheClient->iScreen->RectCompare(
				TRect(originalCursorPos, cursorSize),
				TRect(cleanReferencePos, cursorSize),
				0)); // must not supply CWsScreenDevice::EIncludeTextCursor
		
		return EWait;
		}
	/* Clean up */
	if (iSubState==5)
		{
		++iSubState;
		iWin->CancelTextCursor();
		DestroyWindowL();
		}
	
	iSubState = 0;

	return ENext;
	}

/**
 @SYMTestCaseID				GRAPHICS-WSERV-0375
 @SYMREQ					GT247-CR0714
 @SYMTestCaseDesc			Redirect wserv flickerfree drawing to custom graphics context
 @SYMTestPriority			Medium
 @SYMTestStatus				Implemented
 @SYMTestActions			Redirect wserv flickerfree buffer drawing.
							Action step:
							-Draw opaque window (as background) and transparent window
							-Save screen content to a bitmap
							-Instruct plugin to redirect wserv flickerfree buffer drawing
							-Draw the same opaque window and transparent window again
							-Retrieve plugin bitmap and compare against the saved bitmap
 @SYMTestExpectedResults	Bitmap content match
*/
/**
 @SYMTestCaseID				GRAPHICS-WSERV-0376
 @SYMREQ					GT247-CR0714
 @SYMTestCaseDesc			Stop wserv flickerfree drawing redirection
 @SYMTestPriority			Medium
 @SYMTestStatus				Implemented
 @SYMTestActions			Stop wserv flickerfree buffer drawing redirection.
							Action step:
							-Instruct plugin to stop wserv filckerfree drawing redirection
							-Draw the same opaque and transparent window
							-Save screen content to another bitmap
							-Compare saved bitmap against newly saved bitmap
 @SYMTestExpectedResults	Bitmap content match
*/

TestState CTWsGraphs::TestFlickerRedirectionL()
	{
	if (TransparencySupportedL()==KErrNotSupported)
		{
		++(iTest->iState);
		return ENext;
		}

	// flush transparent window destruction created in TransparencySupportedL before
	// proceeding with the test

	TheClient->iWs.Flush();

	if (iSubState==0)
		{
		_LIT(KTestFlickerRedirection, "TestFlickerRedirection");
		INFO_PRINTF1(KTestFlickerRedirection);

		++iSubState;

		CreateWindowL();
		CreateAlphaWindowL();
		TheClient->iScreen->CopyScreenToBitmap(iBefore);
		DestroyAlphaWindowL();
		DestroyWindowL();
		iRedir->Redirect(CWsRedir::EBackBuffer, ETrue);
		return EWait;
		}

	if (iSubState==1)
		{
		++iSubState;
		CreateWindowL();
		CreateAlphaWindowL();
		TSize sz = iBefore->SizeInPixels();
		TInt bytes = sz.iWidth*sz.iHeight*2; // EColor64K
		iBefore->LockHeap();
		TInt ret=Mem::Compare((const TUint8*)iBackCopy->DataAddress(),bytes,(const TUint8*)iBefore->DataAddress(),bytes);
		TEST(ret==0);
		if (ret!=0)
			{
			_LIT(KLog,"The memory of two bitmaps doesn't match");
			LOG_MESSAGE(KLog);
			}
		iBefore->UnlockHeap();
		DestroyAlphaWindowL();
		DestroyWindowL();
		iRedir->Redirect(CWsRedir::EBackBuffer, EFalse);
		return EWait;
		}

	CreateWindowL();
	CreateAlphaWindowL();
	TheClient->iScreen->CopyScreenToBitmap(iAfter);
	TSize sz = iBefore->SizeInPixels();
	TInt bytes = sz.iWidth*sz.iHeight*2; // EColor64K
	iAfter->LockHeap();
	TEST(Mem::Compare((const TUint8*)iAfter->DataAddress(),bytes,(const TUint8*)iBefore->DataAddress(),bytes)==0);
	iAfter->UnlockHeap();
	DestroyAlphaWindowL();
	DestroyWindowL();

	++(iTest->iState);
	iSubState = 0;
	return ENext;
	}

#endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA

/**
 @SYMTestCaseID				GRAPHICS-WSERV-0377
 @SYMREQ					GT247-CR0714
 @SYMTestCaseDesc			Enable event notification
 @SYMTestPriority			Medium
 @SYMTestStatus				Implemented
 @SYMTestActions			Enable plugin to register to event notification.
							Action step:
							-Instruct plugin to register event handler
							-Draw fullscreen window (plugin will receive window visibility changed event)
							-Query visibility region from plugin side
							-Compare window visible region against value obtained by plugin
 @SYMTestExpectedResults	Visible region match
*/
/**
 @SYMTestCaseID				GRAPHICS-WSERV-0378
 @SYMREQ					GT247-CR0714
 @SYMTestCaseDesc			Disable event notification
 @SYMTestPriority			Medium
 @SYMTestStatus				Implemented
 @SYMTestActions			Disable plugin to register to event notification.
							Action step:
							-Instruct plugin to unregister event handler
							-Destroy fullscreen window (plugin will not receive window visibility changed event)
							-Query visibility region from plugin side

 @SYMTestExpectedResults	Plugin does not receive events notification
*/
TestState CTWsGraphs::TestEventNotificationL()
	{
	if (iSubState==0)
		{
		_LIT(KTestEventNotification, "TestEventNotification");
		INFO_PRINTF1(KTestEventNotification);

		++iSubState;
		iListen->Enable(ETrue);
		CreateWindowL();
		Mem::FillZ(&iListenInfo, sizeof(TListenerInfo));
		TheClient->iWs.Finish();
		TheClient->WaitForRedrawsToFinish();
		iListen->QueryPlugin(iListenInfo);
		return EWait;
		}

	if (iSubState==1)
		{
		++iSubState;
		iListen->Enable(EFalse);
		TEST(iListenInfo.iNumRect==1);
		TEST(iListenInfo.iRect==TRect(TPoint(0,0),TheClient->iScreen->SizeInPixels()));
		DestroyWindowL();
		Mem::FillZ(&iListenInfo, sizeof(TListenerInfo));
		iListen->QueryPlugin(iListenInfo);
		iListen->Enable(EFalse);
		DestroyWindowL();
		return EWait;
		}
		
	TEST(iListenInfo.iNumRect==0);
	
	++(iTest->iState);
	iSubState = 0;
	return ENext;
	}

#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA

TestState CTWsGraphs::TestRedirectionUsingWsBackBufferL()
	{
	if (TransparencySupportedL()==KErrNotSupported)
		{
		++(iTest->iState);
		return ENext;
		}

	// flush transparent window destruction created in TransparencySupportedL before
	// proceeding with the test

	TheClient->iWs.Flush();

	if (iSubState==0)
		{
		_LIT(KTestRedirectionWsBack, "TestRedirectionUsingWsBackBuffer");
		INFO_PRINTF1(KTestRedirectionWsBack);
		
		++iSubState;

		/**
		 @SYMTestCaseID				GRAPHICS-WSERV-0379
		 @SYMTestCaseDesc			Redirect wserv flickerfree to MWsBackBuffer object
		 @SYMTestPriority			Medium
		 @SYMTestStatus				Implemented
		 @SYMTestActions			-Draw opaque window (as background) and transparent window
									-Save screen content to a bitmap
									-Instruct plugin to redirect flickerfree buffer to MWsBackBuffer object
									-Draw the same opaque window and transparent window again
									-Retrieve plugin bitmap and compare against the saved bitmap
		 @SYMTestExpectedResults	Bitmap content match
		*/
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0379"));
		CreateWindowL();
		CreateAlphaWindowL();
		TheClient->iScreen->CopyScreenToBitmap(iBefore);
		DestroyAlphaWindowL();		
		DestroyWindowL();		
		iRedir->RedirectUsingWsBackBuffer(ETrue);
		return EWait;
		}

	if (iSubState==1)
		{
		++iSubState;
		CreateWindowL();
		CreateAlphaWindowL();
		TSize sz = iBefore->SizeInPixels();
		TInt bytes = sz.iWidth*sz.iHeight*2; // EColor64K
		iBefore->LockHeap();
		TInt ret=Mem::Compare((const TUint8*)iBackCopy->DataAddress(),bytes,(const TUint8*)iBefore->DataAddress(),bytes);
		TEST(ret==0);
		if (ret!=0)
			{
			_LIT(KLog,"The memory of two bitmaps doesn't match");
			LOG_MESSAGE(KLog);
			}
		iBefore->UnlockHeap();
		DestroyAlphaWindowL();
		DestroyWindowL();

		/**
		 @SYMTestCaseID				GRAPHICS-WSERV-0380
		 @SYMTestCaseDesc			Restore wserv flickerfree redirection from MWsBackBuffer object
		 @SYMTestPriority			Medium
		 @SYMTestStatus				Implemented
		 @SYMTestActions			-Instruct plugin to stop wserv filckerfree drawing redirection
									-Draw the same opaque and transparent window
									-Save screen content to another bitmap
									-Compare saved bitmap against newly saved bitmap
		 @SYMTestExpectedResults	Bitmap content match
		*/
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0380"));
		iRedir->RedirectUsingWsBackBuffer(EFalse);
		return EWait;
		}

	CreateWindowL();
	CreateAlphaWindowL();
	TheClient->iScreen->CopyScreenToBitmap(iAfter);
	TSize sz = iBefore->SizeInPixels();
	TInt bytes = sz.iWidth*sz.iHeight*2; // EColor64K
	iAfter->LockHeap();
	TEST(Mem::Compare((const TUint8*)iAfter->DataAddress(),bytes,(const TUint8*)iBefore->DataAddress(),bytes)==0);
	iAfter->UnlockHeap();
	DestroyAlphaWindowL();
	DestroyWindowL();
/**
	@SYMTestCaseID	GRAPHICS-WSERV-0527
*/
	((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0527"));
	++(iTest->iState);
	iSubState = 0;
	return ENext;
	}

#endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA

//A call to do coverage through a plugin. 
//This can serve as a basis for future coverage to objects exposed by the
//plugin. For now a single simple test is implmeneted.
TestState CTWsGraphs::TestGraphicDrawerCoverage()
	{
	__ASSERT_ALWAYS(iGdCoverage->RunTest(1)==KErrNone||KErrNotReady, User::Invariant());
	return ENext;
	}

//Simplified non-functional class to create a few dummy CWsGraphicDrawer instances.
//This code is intended to test the Array class, not the Drawer.
//Note that this object is not at all functional! The only guaranteed method is Id().
//WsGraphicDrawer is declared as a friend and is actually intended to be the factory class for CWsGraphicDrawer
class WsGraphicDrawer:public CWsGraphicDrawer
	{
public:
	WsGraphicDrawer()
		{
		}
	//stub for virtual construction. Most members are ignored
	virtual void ConstructL(MWsGraphicDrawerEnvironment& ,const TGraphicDrawerId& id,MWsClient& ,const TDesC8& )
		{
		ConstructL(id);
		}
	//simplified custom construction
	void ConstructL(const TGraphicDrawerId& id)
		{
		MWsGraphicDrawerEnvironment* nullEnv=NULL;
		MWsGraphicDrawerEnvironment& aEnv=*nullEnv;
		MWsClient* nullClient=NULL;
		MWsClient& aOwner=*nullClient;
		this->BaseConstructL(aEnv,id,aOwner);
		this->iDtor_ID_Key=TUid::Null();
		
		}
	//stubs for pure virtual methods
	virtual void HandleMessage(const TDesC8& )
		{}
	virtual void DoDraw(MWsGc& ,const TRect& ,const TDesC8& ) const
		{}
	
	};
//Class to allow me to pre-allocate the CWsGraphicDrawerArray so it doesn't pop up a false-positive memory allocation!
class DummyCleanup:public TCleanupItem
	{
public:
	static void CleanUp(TAny*)		{}
	DummyCleanup(): TCleanupItem(CleanUp,this)	{}
	operator DummyCleanup*()	{	return this;	}
	
	};

//Helper function to explain test fails. Most other tests are against KErrNone
void CTWsGraphs::ReportNegativeResultfail(TInt aLine,TInt aResult,TInt aExpectedResult)
	{
	testBooleanTrue((aResult==aExpectedResult), (TText8*)__FILE__, aLine);
	if (aResult!=aExpectedResult)
		{
		INFO_PRINTF3(_L("Expected return code %i, got %i"),aExpectedResult,aResult);	
		}
	
	}
	
//This is an attempt to use wserv test's pre-existing Panic handler to perform some negative tests.
//At present this handler appears to be broken:
// 1) It doesn't write to the correct html log file
// 2) It no longer writes to the WSERV.LOG file it was writing to a few versions ago
// 3) It doesn't close the panic window so subsequent tests that check the display output fail.
//That was a waste of effort.
struct CTWsGraphs::WrapTestCall
	{
	CTWsGraphs* thisThis;
	TUint		testCount;
	TBool		continueTests;
	TUint 		testFailedLine;
	//This field was intended to allow threaded panicing tests to report other errors
	//As I can't get threaded panicing tests to operate correctly, I have not implemented support for the field.
	//TBuf<1024>	errorMessages;	
		
	WrapTestCall (	CTWsGraphs* thisThis,	TUint		testCount):
		thisThis(thisThis),	testCount(testCount)
		{	continueTests=false;testFailedLine=0;	}
	};
	
TInt	CTWsGraphs::DoNegTestCall(TInt /*aInt*/, TAny *aPtr)
	{
	CTWsGraphs::WrapTestCall* aWrap=static_cast<CTWsGraphs::WrapTestCall*>(aPtr);
	aWrap->continueTests=aWrap->thisThis->NegTestAddSwapGDArrayL(aWrap->testCount,aWrap);	
	return 0;
	}
	
TBool	CTWsGraphs::LaunchNegTestCall(TUint		aTestCount,TUint PanicCode,const TDesC &aPanicCategory)
	{
	WrapTestCall wt(this,aTestCount);
	(void)PanicCode;
	(void)aPanicCategory;
//I have disabled the panicing tests because they don't output diagnostics 
//and the open panic window causes subsequent screen bitmap comparrisson tests to fail.
//	iTest->TestPanicL(DoNegTestCall,aPanicCode,3,&wt,aPanicCategory);
	return wt.continueTests;	
	}

/**
	Loops through all the positive and negative tests associated with the  GraphicDrawerArray.
	The aim is to perform isolated testing of these classes as some are not currently being used.
	
**/
void CTWsGraphs::TestAddSwapGDArrayL()
	{


	INFO_PRINTF1(_L("Positive tests for GraphicDrawerArray"));
	for (TInt i=0;PosTestAddSwapGDArrayL(i);i++)
		{}



	INFO_PRINTF1(_L("Verifying that negative tests for GraphicDrawerArray don't actually panic"));
	for (TInt i=1;NegTestAddSwapGDArrayL(i);i++)
		{}
	}
/**
	Resets and deallocates the GDA withoud deleting the objects.
	@param 	 testArray	the array to reset
	@return true if the array was already empty.
**/
static bool	ResetArray(CWsGraphicDrawerArray& testArray)
{
	bool rv=(testArray.IsEmpty());
	MWsClient* nullClient=NULL;
	testArray.RemoveAll(*nullClient);
	testArray.ResetAndDestroy();		
	return rv;
}
/**
   @SYMTestCaseID GRAPHICS-WSERV-AddSwapGDArray-0001
   @SYMDEF			DEF093926  
  
   @SYMTestCaseDesc DEF093926: Check for stability of Add and Swap unwind methods in isolation.
   		Note that this code is testing the functionality of a class internal to CWindowServer.
   		At present CWindowServer presents just a simple shim on this class, 
   		but if that implementation of  CWindowServer changes than this test will be redudant.
   
   @SYMTestPriority High
   
   @SYMTestStatus Implemented
   
   @SYMTestActions
	The sequence for each of these positive test sections is pretty much the same:
	Add one record with id 1234(test for errors)
	Add one record with id Badf00d
	Swap with another record with id Badf00d
	Remove 2 records
	result=no leaks
	
		Add/Swap: no Cleanup item - no leaks after Remove the added items
   	    AddTLC/SwapTLC: Cleanup item requires Commit - check for no leaks after Remove.
   	    AddTLC/SwapTLC: Cleanup item gets executed by forced Leave  - check for no leaks after.
		AddTLC, SwapTLC in allocation failure scenarios. Add/Swap don't allocate anything!
		obsoleted AddLC/SwapLC to ensure correct function when forced Leave - check for no leaks after
		obsoleted AddLC/SwapLC to ensure correct function. These will always leak in good case.
   @SYMTestExpectedResults 
   		no exceptions or panics within this fn. 
   		only the old AddLC and SwapLC should leak as indicated.
 */
TBool CTWsGraphs::PosTestAddSwapGDArrayL(TInt testcase)
	{
	((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-AddSwapGDArray-0001"));
    CWsGraphicDrawerArray testArray;
    //Represents the memory cached in the array once it has been used even when it is then resized to zero
#if defined(_DEBUG)
    const TInt KArrayMemUseBaseline=1;
#endif
    //Use testArray.IsEmpty() to prove the array is clear when it should be!
    TGraphicDrawerId id1234=  	{  	1234,		EFalse    	};
    TGraphicDrawerId idBADF00D=	{  	0xBADF00D,	EFalse    	};
    WsGraphicDrawer dg1234;		
    dg1234.ConstructL(id1234);
    WsGraphicDrawer dgBADF00D;	
    dgBADF00D.ConstructL(idBADF00D);
    WsGraphicDrawer dgBADF00D_2;
    dgBADF00D_2.ConstructL(idBADF00D);
    CWsGraphicDrawerArray::XRollBackBase* rollBack1;
 	TInt errCode=KErrAbort;
	TInt leaveCode=KErrNone;
	DummyCleanup markerCleanup;
	CleanupStack::PushL(markerCleanup);	 //This allows me to check the stack is clear!
	//expected result of this fn: no exceptions or panics. 
	//Put as much as you like in here, so long as it shouldn't fail.
	
	__UHEAP_MARK;
			__UHEAP_CHECK(0);
	TUint expectedLeakCount=0;
	TBool returnCode=ETrue;
	switch (testcase)
		{
		case 0:

			INFO_PRINTF1(_L("Sub test P0: AddL/Swap: no Cleanup item"));
			TEST(testArray.IsEmpty());
				TRAP(leaveCode,errCode=testArray.Add(&dg1234));
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TEST(!testArray.IsEmpty());
				TRAP(leaveCode,errCode=testArray.Add(&dgBADF00D));
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
				TRAP(leaveCode,errCode=testArray.Swap(&dgBADF00D_2));
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
				TRAP(leaveCode,errCode=testArray.Remove(dg1234.Id()));			
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
				//Note that it is the ID that matters here... dgBADF00D & dgBADF00D_2 have same id.
				TRAP(leaveCode,errCode=testArray.Remove(dgBADF00D_2.Id()));			
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TEST(testArray.IsEmpty());
		break;
		//
		case 1:
			INFO_PRINTF1(_L("Sub test P1: AddTLC/SwapTLC: Cleanup item requires Commit."));
			
			rollBack1=NULL;
			TEST(testArray.IsEmpty());
			TRAP(leaveCode,
				rollBack1=testArray.AddTLC(&dg1234);
				CleanupStack::Check(rollBack1);
				testArray.CommitP(rollBack1);	
				)
			TEST(rollBack1!=NULL);
			TEST(leaveCode==KErrNone);
			TEST(!testArray.IsEmpty());
			rollBack1=NULL;
			TRAP(leaveCode,
				rollBack1=testArray.AddTLC(&dgBADF00D);
				CleanupStack::Check(rollBack1);
				testArray.CommitP(rollBack1);	
				)
			TEST(rollBack1!=NULL);
			TEST(leaveCode==KErrNone);
			rollBack1=NULL;
			TRAP(leaveCode,
				rollBack1=testArray.SwapTLC(&dgBADF00D_2);
				CleanupStack::Check(rollBack1);
				testArray.CommitP(rollBack1);	
				)
			TEST(rollBack1!=NULL);
			TEST(leaveCode==KErrNone);
			rollBack1=NULL;
			TRAP(leaveCode,
				rollBack1=testArray.RemoveTLC(dg1234.Id());
				CleanupStack::Check(rollBack1);
				testArray.CommitP(rollBack1);	
				)
			TEST(rollBack1!=NULL);
			TEST(leaveCode==KErrNone);
			rollBack1=NULL;
				TRAP(leaveCode,
				rollBack1=testArray.RemoveTLC(dgBADF00D_2.Id());			
				CleanupStack::Check(rollBack1);
				testArray.CommitP(rollBack1);	
				)
			TEST(rollBack1!=NULL);
			TEST(leaveCode==KErrNone);
			rollBack1=NULL;
			TEST(testArray.IsEmpty());
		break;
		//
		case 2:
			INFO_PRINTF1(_L("Sub test P2: AddTLC/SwapTLC: Cleanup item gets executed."));
			
			rollBack1=NULL;
			TEST(testArray.IsEmpty());
			TRAP(leaveCode,
				rollBack1=testArray.AddTLC(&dg1234);
				User::Leave(1234);
				);	
			TEST(rollBack1!=NULL);
			TEST(leaveCode==1234);
			TEST(testArray.IsEmpty());
			rollBack1=NULL;
			CleanupStack::Check(markerCleanup);
			__UHEAP_CHECK(KArrayMemUseBaseline);

			TRAP(leaveCode,	errCode=testArray.Add(&dgBADF00D));
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			rollBack1=NULL;
			TRAP(leaveCode,
				rollBack1=testArray.SwapTLC(&dgBADF00D_2);
				User::Leave(1234);
				);	
			TEST(rollBack1!=NULL);
			TEST(leaveCode==1234);
			TEST(!testArray.IsEmpty());
			rollBack1=NULL;
			TRAP(leaveCode,
				rollBack1=testArray.RemoveTLC(dgBADF00D_2.Id());
				TEST(testArray.IsEmpty());
				User::Leave(1234);
				);	
			TEST(rollBack1!=NULL);
			TEST(leaveCode==1234);
			TEST(!testArray.IsEmpty());
			
			
				TRAP(leaveCode,errCode=testArray.Remove(dgBADF00D_2.Id()));			
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TEST(testArray.IsEmpty());
			rollBack1=NULL;
		break;
		//
		case 3:
			INFO_PRINTF1(_L("Sub test P3: AddLC/SwapLC: Cleanup item gets executed - doesn't leak"));
			TEST(testArray.IsEmpty());
			TRAP(leaveCode,
				testArray.AddLC(&dg1234);
				User::Leave(1234);
				);	
			TEST(leaveCode==1234);
			TEST(testArray.IsEmpty());
			rollBack1=NULL;
		__UHEAP_CHECK(KArrayMemUseBaseline);	  //because it threw it didn't leak
			
			//use my new method to add the object to be swapped out so no leak
			TRAP(leaveCode,errCode=testArray.Add(&dgBADF00D));
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
		__UHEAP_CHECK(KArrayMemUseBaseline);	  //new method doesn't leak.
			rollBack1=NULL;
			TRAP(leaveCode,
				errCode=testArray.SwapLC(&dgBADF00D_2);
				User::Leave(1234);
				);	
			TEST(errCode==KErrNone);
			TEST(leaveCode==1234);
			TEST(!testArray.IsEmpty());
			
				TRAP(leaveCode,errCode=testArray.Remove(dgBADF00D_2.Id()));			
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TEST(testArray.IsEmpty());
			rollBack1=NULL;
		break;
		//
		case 4:
	
		//I don't really care whether the individual calls succeed or fail, 
		//just whether it leaks overall, and that the error codes correspond to no-action
		for (TInt faultRate=1;faultRate<5;faultRate++)
			{
			INFO_PRINTF2(_L("Sub test P4: Add/Swap: memory faulting %i"),faultRate);
			__UHEAP_SETFAIL(RAllocator::EDeterministic,faultRate);
			TInt err1=KErrNone;
			rollBack1=NULL;
			TRAP(leaveCode,
				errCode=testArray.Add(&dg1234);
				)
			err1=errCode;
			__UHEAP_SETFAIL(RAllocator::ENone,0);
			TRAP(leaveCode,errCode=testArray.Add(&dgBADF00D));
			__UHEAP_SETFAIL(RAllocator::EDeterministic,faultRate);
			rollBack1=NULL;
			TRAP(leaveCode,
				errCode=testArray.Swap(&dgBADF00D_2);
				)
			__UHEAP_SETFAIL(RAllocator::ENone,0);
			//If the first Add fails then the object should not be removed
			if (!err1)
				{
				TRAP(leaveCode,errCode=testArray.Remove(dg1234.Id()));			
				TEST(errCode==KErrNone);
				TEST(leaveCode==KErrNone);
				}
			//If the swap fails, then the add still needs to be removed
			//Note that it is the ID that matters here... dgBADF00D & dgBADF00D_2 have same id.
			TRAP(leaveCode,errCode=testArray.Remove(dgBADF00D_2.Id()));			
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TEST(testArray.IsEmpty());
			ResetArray(testArray);
			CleanupStack::Check(markerCleanup);
			__UHEAP_CHECK(0);
			}
		break;
		//
		case 5:
				
		//I don't really care whether the individual calls succeed or fail, 
		//just whether it leaks overall, and that the error codes correspond to no-action
		for (TInt faultRate=1;faultRate<5;faultRate++)
			{
			INFO_PRINTF2(_L("Sub test P5: AddTLC/SwapTLC: memory faulting %i"),faultRate);
			__UHEAP_SETFAIL(RAllocator::EDeterministic,faultRate);
			TInt err1=KErrNone,err2=KErrNone,err3=KErrNone;
			rollBack1=NULL;
			TRAP(leaveCode,
				rollBack1=testArray.AddTLC(&dg1234);
				CleanupStack::Check(rollBack1);
				testArray.CommitP(rollBack1);	
				)
			err1=leaveCode;
			__UHEAP_SETFAIL(RAllocator::ENone,0);
			TRAP(leaveCode,errCode=testArray.Add(&dgBADF00D));
			__UHEAP_SETFAIL(RAllocator::EDeterministic,faultRate);
			rollBack1=NULL;
			TRAP(leaveCode,
				rollBack1=testArray.SwapTLC(&dgBADF00D_2);
				CleanupStack::Check(rollBack1);
				testArray.CommitP(rollBack1);	
				)
			//If the first Add fails then the object should not be removed
			if (!err1)
				{
				TRAP(leaveCode,
					rollBack1=testArray.RemoveTLC(dg1234.Id());			
					CleanupStack::Check(rollBack1);
					testArray.CommitP(rollBack1);	
					)
				err2=leaveCode;
				}
			//If the swap fails, then the add still needs to be removed
			//Note that it is the ID that matters here... dgBADF00D & dgBADF00D_2 have same id.
			TRAP(leaveCode,
					rollBack1=testArray.RemoveTLC(dgBADF00D_2.Id());
					CleanupStack::Check(rollBack1);
					testArray.CommitP(rollBack1);	
					)
			err3=leaveCode;
			
			
			__UHEAP_SETFAIL(RAllocator::ENone,0);
			//If the Removes failed then the object should be removed again
			if (err2)
				{
				TRAP(leaveCode,errCode=testArray.Remove(dg1234.Id()));			
				TEST(errCode==KErrNone);
				TEST(leaveCode==KErrNone);
				}
			if (err3)
				{
				TRAP(leaveCode,errCode=testArray.Remove(dgBADF00D_2.Id()));			
				TEST(errCode==KErrNone);
				TEST(leaveCode==KErrNone);
				}
			TEST(testArray.IsEmpty());
			ResetArray(testArray);
			CleanupStack::Check(markerCleanup);
			__UHEAP_CHECK(0);
			}
				
		break;
		//
		case 6:
	//this set does leak:
	
		INFO_PRINTF1(_L("Sub test P6: AddLC/SwapLC: Cleanup item gets popped - unfixable leaks"));
			TEST(testArray.IsEmpty());
			TRAP(leaveCode,
				testArray.AddLC(&dg1234);
				CleanupStack::Pop();
				);	
			TEST(leaveCode==KErrNone);
			TEST(!testArray.IsEmpty());
		
		CleanupStack::Check(markerCleanup);
		__UHEAP_CHECK(KArrayMemUseBaseline+1);	
			
			TRAP(leaveCode,
				testArray.AddLC(&dgBADF00D);
				CleanupStack::Pop();
				)
			TEST(leaveCode==KErrNone);
		CleanupStack::Check(markerCleanup);
		__UHEAP_CHECK(KArrayMemUseBaseline+2);	
			rollBack1=NULL;
			TRAP(leaveCode,
				errCode=testArray.SwapLC(&dgBADF00D_2);
				CleanupStack::Pop();
				);	
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TEST(!testArray.IsEmpty());
				TRAP(leaveCode,errCode=testArray.Remove(dg1234.Id()));			
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
				TRAP(leaveCode,errCode=testArray.Remove(dgBADF00D_2.Id()));			
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TEST(testArray.IsEmpty());
			rollBack1=NULL;
			expectedLeakCount=3;
		break;
		//
		case 7:
			returnCode=EFalse;
		break;
		}
	ResetArray(testArray);
	CleanupStack::Check(markerCleanup);
	__UHEAP_CHECK(expectedLeakCount);
	__UHEAP_MARKENDC(expectedLeakCount);
	if (expectedLeakCount!=0)
		{	//Ensure that the leaked items are no longer associated with this debug level.
			//Note that __DbgSetAllocFail(FALSE,RAllocator::EReset,1) resets the debug level to 0, 
			//so levels can't be nested when using this call.
		__UHEAP_MARK;			
	    __UHEAP_TOTAL_RESET;	
		INFO_PRINTF2(_L("Anticipated %i leaks declassified"),expectedLeakCount);	//can't get here if wrong
		}
			
	CleanupStack::PopAndDestroy(markerCleanup);
	((CTWsGraphsStep*)iStep)->RecordTestResultL();
	return returnCode;
	}

/**
	@param 	failcase		index to test to perform
	@param	aWrappedParams  represents inter-thread information when test is run on a private thread
				if aWrappedParams is NULL then the test is running on the main thread.
	@return true if there are higher-numbered fail cases.

   @SYMTestCaseID GRAPHICS-WSERV-NegAddSwapGDArray-0001
   @SYMDEF			DEF093926  
  
   @SYMTestCaseDesc DEF093926: Check for stability of Add and Swap unwind methods in isolation,
   					specifically checking that bad inputs are rejected gracefully.
   		Note that this code is testing the functionality of a class internal to CWindowServer.
   		At present CWindowServer presents just a simple shim on this class, 
   		but if that implementation of  CWindowServer changes than this test will be redudant.
   
   @SYMTestPriority High
   
   @SYMTestStatus Implemented
   
   @SYMTestActions
   
		Add/Swap: no Cleanup item - no leaks after Remove the added items
   	    AddTLC/SwapTLC: Cleanup item requires Commit - check for no leaks after Remove.
   	    AddTLC/SwapTLC: Cleanup item gets executed by forced Leave  - check for no leaks after.
		AddTLC, SwapTLC in allocation failure scenarios. Add/Swap don't allocate anything!
		obsoleted AddLC/SwapLC to ensure correct function when forced Leave - check for no leaks after
		obsoleted AddLC/SwapLC to ensure correct function. These will always leak in good case.
	Calls NegTestAddSwapGDArrayL.	
	case 1/2/3: Tests AddL, AddLC, AddTLC that a NULL input is rejected
	case 4/5/6: Tests SwapL, SwapLC, SwapTLC that a NULL input is rejected
	case 7/8/9: Tests AddL, AddLC, AddTLC that a repeat input is rejected
	case 10/11/12: Tests SwapL, SwapLC, SwapTLC that a non-repeat input is rejected
   @SYMTestExpectedResults 
 */
TBool CTWsGraphs::NegTestAddSwapGDArrayL(TInt failcase,WrapTestCall*aWrappedParams)
	{
	((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-NegAddSwapGDArray-0001"));
	_LIT(KCategory,"WsGraphicDrawer");
	if (!aWrappedParams)
		{
		INFO_PRINTF2(_L("NegTestAddSwapGDArrayL Negative sub test %i"),failcase);
		};
    CWsGraphicDrawerArray testArray;
    TGraphicDrawerId id1234=  	{  	1234,		EFalse    	};
    TGraphicDrawerId idBADF00D=	{  	0xBADF00D,	EFalse    	};
    WsGraphicDrawer dg1234;		
    dg1234.ConstructL(id1234);
    WsGraphicDrawer dgBADF00D;	
    dgBADF00D.ConstructL(idBADF00D);
    WsGraphicDrawer dgBADF00D_2;
    dgBADF00D_2.ConstructL(idBADF00D);
    CWsGraphicDrawerArray::XRollBackBase* rollBack1=NULL;
 	TInt errCode=KErrAbort;
	TInt leaveCode=KErrNone;
	TBool	returnMoreTests=ETrue;
	DummyCleanup markerCleanup;
	TBool mayPanic=EFalse;
#ifdef __WINS__
	mayPanic=ETrue;
#endif

	CleanupStack::PushL(markerCleanup);	 //This allows me to check the stack is clear!
	__UHEAP_MARK;
	
	switch (failcase)
		{
		case 1:	//NULL arg: expected result:  returns KErrArgument
	    	TRAP(leaveCode,
	    		errCode=testArray.Add(NULL);
	    		)
			TEST(leaveCode==KErrNone);
	    	ReportNegativeResultfail(__LINE__,errCode,KErrArgument);
	    break;
		case 2:	//NULL arg: expected result: throws KErrArgument
			TRAP(leaveCode,	
				rollBack1=testArray.AddTLC(NULL);
				TEST(EFalse);	//Should never get here!
				)
			TEST(rollBack1==NULL);
	    	ReportNegativeResultfail(__LINE__,leaveCode,KErrArgument);
	    break;
		case 3:	//NULL arg: expected result: debug: panic. In release doesn't return any information!
			if (!aWrappedParams && mayPanic)
				{
			    LaunchNegTestCall(failcase,EWsGraphicDrawerPanicBadArgument,KCategory);
				}
			else
				{
				TRAP(leaveCode,
					testArray.AddLC(NULL);
					User::Leave(1234);  //Panics before here in debug. No leak if cleanup is taken.
					);	
				TEST(leaveCode==1234);	//Panics before here in debug
				}
	    break;
		//
		case 4:	//NULL arg: expected result: returns KErrArgument
	    	TRAP(leaveCode,
	    		errCode=testArray.Swap(NULL)
	    		)
			TEST(leaveCode==KErrNone);
	    	ReportNegativeResultfail(__LINE__,errCode,KErrArgument);
	    break;
		case 5:	//expected result:  throws KErrArgument
			TRAP(leaveCode,
				rollBack1=testArray.SwapTLC(NULL);
				testArray.CommitP(rollBack1);
				)
			TEST(rollBack1==NULL);
	    	ReportNegativeResultfail(__LINE__,leaveCode,KErrArgument);
	    break;
		case 6:	//NULL arg: expected result: debug: panic. In release doesn't return any information!
			if (!aWrappedParams && mayPanic)
				{
			    LaunchNegTestCall(failcase,EWsGraphicDrawerPanicBadArgument,KCategory);
				}
			else
				{
				TRAP(leaveCode,
					errCode=testArray.SwapLC(NULL);
					User::Leave(1234);  //Panics before here in debug. No leak if cleanup is taken.
					);
				TEST(leaveCode==1234);	//Panics before here in debug
				TEST(errCode==KErrNotFound);
				}
		break;
		//
		case 7:	//Add overwrites: expected result: returns KErrAlreadyExists
	    	TRAP(leaveCode,
	    		errCode=testArray.Add(&dg1234);
	    		)
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
	    	TRAP(leaveCode,
	    		errCode=testArray.Add(&dg1234);		//oops! Already added!
	    		)
			TEST(leaveCode==KErrNone);
	    	ReportNegativeResultfail(__LINE__,errCode,KErrAlreadyExists);
	    break;
		case 8:	//Add overwrites: expected result:  throws KErrAlreadyExists
	    	TRAP(leaveCode,
	    		errCode=testArray.Add(&dg1234);
	    		)
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TRAP(leaveCode,	
				rollBack1=testArray.AddTLC(&dg1234);		//oops! Already added!
				testArray.CommitP(rollBack1);
				)
			TEST(rollBack1==NULL);
	    	ReportNegativeResultfail(__LINE__,leaveCode,KErrAlreadyExists);
	    break;
		case 9:	//Add overwrites: expected result: debug: does not panic, but throws KErrAlreadyExists.
	    	TRAP(leaveCode,
	    		errCode=testArray.Add(&dg1234);
	    		)
			TEST(errCode==KErrNone);
			TEST(leaveCode==KErrNone);
			TRAP(leaveCode,
					testArray.AddLC(&dg1234);		//oops! Already added! Should leave.
					User::Leave(1234);  //Should leave before here! No leak if cleanup is taken.
				);	
	    	ReportNegativeResultfail(__LINE__,leaveCode,KErrAlreadyExists);
	    break;
		//
		case 10:	//Swap empty slot: expected result:  returns KErrNotFound
	    	TRAP(leaveCode,
	    		errCode=testArray.Swap(&dg1234) 		//oops! Nothing to swap with!
	    		)
			TEST(leaveCode==KErrNone);
	    	ReportNegativeResultfail(__LINE__,errCode,KErrNotFound);
	    break;
		case 11:	//Swap empty slot: expected result: throws KErrNotFound
			TRAP(leaveCode,
				rollBack1=testArray.SwapTLC(&dg1234);		//oops! Nothing to swap with!
				testArray.CommitP(rollBack1);
				)
			TEST(rollBack1==NULL);
	    	ReportNegativeResultfail(__LINE__,leaveCode,KErrNotFound);
	    break;
		case 12:	//Swap empty slot: expected result: debug: panic. In release doesn't return any information!
			if (!aWrappedParams && mayPanic)
				{
			    LaunchNegTestCall(failcase,EWsGraphicDrawerPanicBadArgument,KCategory);
				}
			else
				{
				TRAP(leaveCode,
					errCode=testArray.SwapLC(&dg1234);		//oops! Nothing to swap with!
					User::Leave(1234);  //Panics before here in debug. No leak if cleanup is taken.
					);	
				TEST(leaveCode==1234);			//Panics before here in debug
				TEST(errCode==KErrNotFound);	//Panics before here in debug
				}
	    break;
	    
		//
		default:
			returnMoreTests=EFalse;
		}
	ResetArray(testArray);
	CleanupStack::Check(markerCleanup);
	__UHEAP_CHECK(0);
	__UHEAP_MARKENDC(0);
    testArray.Close();
//    CWsGraphicDrawerArray::testArrayValidator::ResetArray(&testArray);
	CleanupStack::PopAndDestroy(markerCleanup);
	return returnMoreTests;
	}

/**
   @SYMTestCaseID 	GRAPHICS-WSERV-LeakInService-0001
   @SYMDEF			DEF093926  
   @SYMTestCaseDesc Check for leaks over repeated re-assignments.
   
   @SYMTestPriority High
   
   @SYMTestStatus Implemented
   
   @SYMTestActions 
   Repeatedly create the same bitmap instance
   After a few initial wobbles in the server-side HeapCount it should not increase
   5 calls are made without checking the level, then 5 more check the level.
   Note that as we are testing the main server heap, 
   other threads may interrupt and perform operations that change the memory figures.
   
   @SYMTestExpectedResults The CWsGraphicBitmap objects are created and no leaks are reported.
 */	
void CTWsGraphs::DoTestLeakInServiceL()
	{
		INFO_PRINTF1(_L("DoTestLeakInServiceL"));
		const TInt prepCount=5;
		const TInt testCount=5;
		
				
		TUid uid1 = {0x10000001};
		TUid uid2 = {0x10000002};
		 
		TWsGraphicId twsGraphicId1(uid1);
		TEST(twsGraphicId1.Uid()==uid1);
		
		TWsGraphicId twsGraphicId2(uid2);
		TEST(twsGraphicId2.Uid()==uid2);
		
		TWsGraphicId twsGraphicId3(twsGraphicId2);
		TEST(twsGraphicId3.Uid()==uid2);
		
		TWsGraphicId twsGraphicId4(1);
		twsGraphicId4.Set(uid1);
		TEST(twsGraphicId4.Uid()==uid1);		

		TSize screenSize = TheClient->iScreen->SizeInPixels();
		
		__UHEAP_RESET;
		__UHEAP_MARK;
		// Create local shared CWsGraphicBitmap	
		// Repeat operation for any sign of memory leak...	
		CFbsBitmap bitmap2;
		CFbsBitmap mask2;		
		
		bitmap2.Create(screenSize,TheClient->iScreen->DisplayMode());
		mask2.Create(bitmap2.SizeInPixels(),TheClient->iScreen->DisplayMode());
			
		TInt c0=TheClient->iWs.HeapCount();
		CWsGraphicBitmap* bTestX = CWsGraphicBitmap::NewL(twsGraphicId2.Uid(), &bitmap2,&mask2);		
		for (TInt i=0;i<prepCount;i++)
			{
			//TInt c2=TheClient->iWs.HeapCount();
			delete bTestX; 								
			//TInt c3=TheClient->iWs.HeapCount();
			bTestX = CWsGraphicBitmap::NewL(twsGraphicId2.Uid(), &bitmap2,&mask2);		
			//TInt c4=TheClient->iWs.HeapCount();
			}
		// Give WSERV a chance to settle.
		TheClient->iWs.Finish();
		User::After (1000000); //1s
		
		TInt c1=TheClient->iWs.HeapCount();
		TInt failures=0;
		for (TInt i=0;i<testCount;i++)
			{
			TInt c2=TheClient->iWs.HeapCount();
			delete bTestX;
			//TInt c3=TheClient->iWs.HeapCount();
			//The heap count doesn't go down after delete operation
			//because the delete message is buffered by the server, because it does not have a return value.
			//Aparrently, although CWsGraphicBitmap and TheClient terminate at the same server,
			//and use the same general heap (I have tested this under debug),
			//they do not share the same session, so flushing TheClient does not effect CWsGraphicBitmap
			bTestX = CWsGraphicBitmap::NewL(twsGraphicId2.Uid(), &bitmap2,&mask2);		
			
			// Give WSERV a chance to settle.
			TheClient->iWs.Finish();
			User::After (1000000); //1s

			TInt c4=TheClient->iWs.HeapCount();   
			//Can compare immediately after allocation as the server doesn't buffer the create command.
			if (!(c2==c4))
				{
				if (c4 > c2) // only fail the test if the count has increased
					{
					failures++;
					}
				INFO_PRINTF2(_L("Server Heap count change accross delete/new = %i"),c4-c2);
				}
			}
		// Outside of main loop to avoid client/wserv interaction during test.
		TEST(failures==0);
		TInt c5=TheClient->iWs.HeapCount();
		TEST((c1-c5)/testCount==0);	   //If every call leaked.
		if ((c1-c5)/testCount)
			{
			INFO_PRINTF3(_L("Server Heap count change accross %i delete/new cycles = %i"),testCount,c5-c1);
			INFO_PRINTF3(_L("Before %i / After %i"),c1,c5);
			}
		
		delete bTestX; 
		
		__UHEAP_CHECK(0);
		__UHEAP_MARKEND;
		
	}
/**
 @SYMTestCaseID				GRAPHICS-WSERV-0381 
 @SYMDEF					DEF095063
 @SYMTestCaseDesc			Test case for INC098114 CWsGraphicDrawer::SendMessage panics window server
 @SYMTestPriority			Medium
 @SYMTestStatus				Implemented
 @SYMTestActions			Enable the test flag and reproduce the defect
							Action step:
							-Instruct plugin to register event handler
							-Draw fullscreen window (plugin will receive window visibility changed event)
							-Set the test flag 
							-Query visibility region from plugin side
							-Instruct plugin to unregister event handler
							-Destroy fullscreen window (plugin will not receive window visibility changed event)
						
 @SYMTestExpectedResults	wserv should not panic with the fix
*/	

TestState CTWsGraphs::TestSuccessiveMessageL()
	{
	if (iSubState==0)
		{
		_LIT(KTestSuccessiveMessage, "TestSuccessiveMessage");
		INFO_PRINTF1(KTestSuccessiveMessage);

		++iSubState;
		iListen->Enable(ETrue);
		CreateWindowL();
		Mem::FillZ(&iListenInfo, sizeof(TListenerInfo));
		//Set the test flag to enable the reproduction of defect
		iListen->SetTestFlag();
		iListen->QueryPlugin(iListenInfo);
		iListen->Enable(EFalse);
		DestroyWindowL();
		return EWait;
		}

	++(iTest->iState);
	iSubState = 0;
	return ENext;
	}

TestState CTWsGraphs::TestWindowGroupChangeL()
	{
	if (iSubState==0)
		{
		_LIT(KTestWindowGroupChange, "TestWindowGroupChange");
		INFO_PRINTF1(KTestWindowGroupChange);

		++iSubState;
		iListen->Enable(ETrue);
		CreateWindowL();
		Mem::FillZ(&iListenInfo, sizeof(TListenerInfo));
		iListen->QueryPlugin(iListenInfo);
		return EWait;
		}

	if (iSubState==1)
		{
		++iSubState;
		iOriginalWindowGroupId = iListenInfo.iWindowGroupId;
		iNewWin = CCrWin::NewL(iTest->iScreenNumber, ETrue);
		iListen->QueryPlugin(iListenInfo);
		return EWait;
		}

	TEST(iListenInfo.iWindowGroupId != iOriginalWindowGroupId);
	
	delete iNewWin;
	iNewWin = NULL;
	iListen->Enable(EFalse);
	DestroyWindowL();
	++(iTest->iState);
	iSubState = 0;
	return ENext;
	}

/**
 @SYMTestCaseID				GRAPHICS-WSERV-0382
 @SYMDEF 					INC085451
 @SYMTestCaseDesc			Test Animation frame rate
 @SYMTestPriority			Medium
 @SYMTestStatus				Implemented
 @SYMTestActions			Simulate an Animation artwork by calling DrawWsGraphic and DoDraw.
							Action step:
							-Calls DrawWsGraphic for two different animations with different frame rates
							-Retrieve the frame count for two differnt frames per seconds
							-Test the two frame rate shouldn't be same.

 @SYMTestExpectedResults	Animation Frame rate should be different for different frames per second
*/
TestState CTWsGraphs::TestFrameRateL()
	{
	//Check for Transparency enabled in wsini.ini
	if (TransparencySupportedL()==KErrNotSupported)
		{
		++(iTest->iState);
		return ENext;
		}

	// flush transparent window destruction created in TransparencySupportedL before
	// proceeding with the test
	TheClient->iWs.Flush();

	//Here 	iSubState is 0, when this functions executes first time 
	//		iSubState is 1 means the call is from a callback function.
	if(iSubState == 0)
		{
		_LIT(KTestFrameRate, "TestFrameRate");
		INFO_PRINTF1(KTestFrameRate);

		++iSubState;
		iTestframerate = CGraphicTestFrameRate::NewL(iTest->iScreenNumber);

		//Set the callback function
		iTestframerate->SetCallBack(TCallBack(CTWsGraphs::PluginCallBack,this));

		//Create the window and call the graphic animation
		CreateWindowL(EFalse);
		iWin->DrawGraphic(iTestframerate->Id().Id());
		return EWait;
		}

	//PeterI wait a while for animations to redraw then query the plugin
	User::After(2000000);
	TheClient->iWs.Flush();
	TheClient->WaitForRedrawsToFinish();
	TheClient->iWs.Finish();

	//Invoke the plug-in and get the counter value
	Mem::FillZ(&iAnimCount, sizeof(TAnimRate));

	iTestframerate->QueryPlugin(iAnimCount);
	TheClient->iWs.Flush();
	TheClient->WaitForRedrawsToFinish();
	TheClient->iWs.Finish();

	//Compare and test the total frame rate for two different frame counts....
	TEST((iAnimCount.iAnim1>0 && iAnimCount.iAnim2>0) && iAnimCount.iAnim1 !=iAnimCount.iAnim2);
	if(iSubState == 1)
		{
		DestroyWindowL();
		delete iTestframerate;
		}
	++(iTest->iState);
	iSubState = 0;
	return ENext;
	}

/**
 @SYMTestCaseID				GRAPHICS-WSERV-0438 
 @SYMDEF					INC103472
 @SYMTestCaseDesc			CRedrawRegion::ContainsDrawers does not look for all drawers 
 @SYMTestPriority			Medium
 @SYMTestStatus				Implemented
 @SYMTestActions			Create ECom-plugins to enable the scenario, in which there is one simple and one container drawer. 
 							In the container drawer, two other simple drawers are enabled. Each drawer draws a coloured ellipse.
 							In this case, when the contained drawer is requested to change the colour of the ellipse, the screen will not be updated
 							without the fix.  
 							Action step:
							-Create four CRP graphics.
							-Call the simple drawer and container drawer to draw ellipses. The container drawer
							 also enables two other simple drawers to draw ellipses in different colors.
							-Update the color of each ellipse in turn. 
							-Check that the screen display is as required.						
 @SYMTestExpectedResults	The colour of each ellipse residing in the drawers is successfully updated. Those for the contained drawers wont be updated without the fix. 
*/	
void CTWsGraphs::TestNestedDrawerCRP()
	{
	_LIT(KTestContainDrawer, "Test INC103472: A Contained Drawer");
	INFO_PRINTF1(KTestContainDrawer);

	RWindow window1(TheClient->iWs);
	CleanupClosePushL(window1);
	User::LeaveIfError(window1.Construct(*TheClient->iGroup->GroupWin(), ENullWsHandle));
	
	window1.EnableRedrawStore(ETrue);	// Force to enable the redraw storing
	window1.SetRequiredDisplayMode(EColor256);	 // Do not set window size here to avoid hardware test failure
	window1.SetBackgroundColor(KRgbDarkGreen);
	window1.Activate();
	
	// A simple graphic
	CWsSimpleGraphicBitmap* wsGraphic1 = CWsSimpleGraphicBitmap::NewL(KSimpleDrawerInterfaceId);
	CleanupStack::PushL(wsGraphic1);
	// A container graphic
	CWsContainGraphicBitmap* wsGraphic2 = CWsContainGraphicBitmap::NewL(KContainDrawerInterfaceId);
	CleanupStack::PushL(wsGraphic2);
	// A contained graphic residing in the container graphic wsGraphic2 
 	CWsSimpleGraphicBitmap* wsGraphic3 = CWsInvisibleGraphicBitmap1::NewL(KInvisibleDrawerInterfaceId1);
 	CleanupStack::PushL(wsGraphic3);
	// A contained graphic residing in the container graphic wsGraphic2
 	CWsSimpleGraphicBitmap* wsGraphic4 = CWsInvisibleGraphicBitmap2::NewL(KInvisibleDrawerInterfaceId2);
 	CleanupStack::PushL(wsGraphic4);

    window1.Invalidate();
	window1.BeginRedraw();
	TheClient->iGc->Activate(window1);
	TheClient->iGc->Clear();
	// Call CRP drawer to draw the coloured ellipses	
	TheClient->iGc->DrawWsGraphic(wsGraphic1->Id(),TRect(TPoint(20,20),TSize(300,100)));
	TheClient->iGc->DrawWsGraphic(wsGraphic2->Id(),TRect(TPoint(20,100),TSize(300,100)));	

    TheClient->iGc->Deactivate();
	window1.EndRedraw();
	TheClient->Flush();			   
	
	// Update the colour of four ellipses residing in four CRP drawers. 
	TInt err = wsGraphic1->UpdateColor(KRgbRed);
	TEST(KErrNone == err);
	err = wsGraphic2->UpdateColor(KRgbDarkBlue);
	TEST(KErrNone == err);
	// If the fix is not inserted, the colour of the third and fourth ellipses residing in the contained drawers wont be updated
	err = wsGraphic3->UpdateColor(KRgbDarkMagenta);
	TEST(KErrNone == err);
	err = wsGraphic4->UpdateColor(KRgbDarkCyan);	  //won't change the displayed color if there is a right place for flush()
	TEST(KErrNone == err);
	
	TheClient->Flush();
 	// Force some delays to wait until the color change
    User::After(2000000);
    // Test whether the screen content is changed as required
    CheckResult();
   	CleanupStack::PopAndDestroy(5,&window1);
	}

// Check the screen display with the reference bitmap to ensure the color to be updated correctly
void CTWsGraphs::CheckResult()
	{
    TSize size = TSize(320,200);//The maximum size of the screen content we are looking at

    // Create a reference bitmap
    CFbsBitmap* bitmapRef = new(ELeave) CFbsBitmap;
   	CleanupStack::PushL(bitmapRef);
	User::LeaveIfError(bitmapRef->Create(size, EColor256));
	CFbsBitGc* gc;
	CFbsBitmapDevice* bitmapDev = CFbsBitmapDevice::NewL(bitmapRef);
	TEST(bitmapDev!=NULL);
   	CleanupStack::PushL(bitmapDev);
	User::LeaveIfError(bitmapDev->CreateContext(gc));
   	CleanupStack::PushL(gc);
	gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	gc->SetBrushColor(KRgbDarkGreen);
	gc->Clear(TRect(TPoint(0,0), size));//background dark green
	gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
    gc->SetBrushColor(KRgbRed);
	gc->DrawEllipse(TRect(TPoint(20,20),TSize(300,100)));  //map to the simple drawer
	gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	gc->SetBrushColor(KRgbDarkBlue);
	gc->DrawEllipse(TRect(TPoint(20,100),TSize(300,100)));	//map to the container drawer
	gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	gc->SetBrushColor(KRgbDarkMagenta);
	gc->DrawEllipse(TRect(TPoint(100,150),TSize(50,50)));	//map to the contained drawer
	gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
 	gc->SetBrushColor(KRgbDarkCyan);
	gc->DrawEllipse(TRect(TPoint(200,150),TSize(50,50)));	//map to the contained drawer
    TInt bitmapHeight = bitmapRef->SizeInPixels().iHeight;
	TInt bitmapWidth = bitmapRef->SizeInPixels().iWidth;
  
   	// Copy the screen content to bitmap
	INFO_PRINTF1(_L("Capture screen content."));
	CFbsBitmap* screenBitmap = new(ELeave) CFbsBitmap();
	CleanupStack::PushL(screenBitmap);
	User::LeaveIfError(screenBitmap->Create(size, TheClient->iScreen->DisplayMode()));
	TRect rct = TRect(TPoint(0,0), size);
	User::LeaveIfError(TheClient->iScreen->CopyScreenToBitmap(screenBitmap,rct));

	// Compare the displayed bitmap against the reference one
	INFO_PRINTF1(_L("Compare the displayed bitmap against the expected one."));
	TInt lineLength=bitmapRef->ScanLineLength(bitmapWidth, EColor256);
	HBufC8* compareLineBuf=HBufC8::NewLC(lineLength);
	TPtr8 compareLinePtr(compareLineBuf->Des());
	HBufC8* screenLineBuf=HBufC8::NewLC(lineLength);
	TPtr8 screenLinePtr(screenLineBuf->Des());
	for (TInt index=0; index<bitmapHeight; index++)
		{
		bitmapRef->GetScanLine(compareLinePtr, TPoint(0,index), bitmapWidth, EColor256);
		screenBitmap->GetScanLine(screenLinePtr, TPoint(0,index),bitmapWidth, EColor256);
		TInt compareResult=compareLinePtr.Compare(screenLinePtr);
		if (compareResult!=0)
			{
			INFO_PRINTF2(_L("Scanline compare failed: %d"),index);
			TEST(EFalse);
			break;
			}
		}
	CleanupStack::PopAndDestroy(6,bitmapRef);  

	} 

void ResetScreenMode(TAny* aAny)
	{
	CWsScreenDevice* screen=static_cast<CWsScreenDevice*>(aAny);
	screen->SetScreenMode(0);
	screen->SetAppScreenMode(0);
	}

#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA

void CTWsGraphs::TestScreenModeChangeL()
	{
	_LIT(KLog,"Screen Doesn't match bitmap.  Size=(%d,%d) winSizeMode=%d redrawMode=%d modeIndex=%d");
// A simple CRP graphic to draw in the test
	CWsSimpleGraphicBitmap* wsGraphic1=CWsSimpleGraphicBitmap::NewL(KSimpleDrawerInterfaceId);
	CleanupStack::PushL(wsGraphic1);
	RWindow testWin(TheClient->iWs);
	CleanupClosePushL(testWin);
	User::LeaveIfError(testWin.Construct(*TheClient->iGroup->GroupWin(),0xbadbad));
	testWin.SetRequiredDisplayMode(EColor64K);
	testWin.Activate();
// Cleanup display mode by setting back to 0 if we leave in the tests
	CleanupStack::PushL(TCleanupItem(ResetScreenMode,TheClient->iScreen));
	TInt numScreenModes=TheClient->iScreenModes.Count();
	TBool match;

	for(TInt winSizeMode=0;winSizeMode<2;winSizeMode++)
		{ // Two size modes, fullScreen and non-full screen
		for(TInt redrawMode=0;redrawMode<2;redrawMode++)
			{ // Two redraw modes to test drawing inside and outside of a redraw.
			const TBool drawInsideRedraw=(redrawMode==0);
			for(TInt modeIndex=0;modeIndex<numScreenModes;modeIndex++)
				{
				const TInt screenMode=TheClient->iScreenModes[modeIndex];
				const TPoint origin=TheClient->iScreen->GetScreenModeScaledOrigin(screenMode);
				if (origin.iX!=0 || origin.iY!=0)
					continue;
				// Enable redirection before changing screen mode as this is what we are testing
				iRedir->Redirect(CWsRedir::EFrontBuffer, ETrue);
				TheClient->iScreen->SetAppScreenMode(screenMode);
				TheClient->iScreen->SetScreenMode(screenMode);

				TPixelsAndRotation sizeAndRotation;
				TheClient->iScreen->GetDefaultScreenSizeAndRotation(sizeAndRotation);
//
				TSize screenSize(TheClient->iScreen->SizeInPixels());
				if(sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationRotated90 || 
						sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationRotated270)
					{
					screenSize.iWidth = Min(screenSize.iWidth, 240);//to make sure we won't exceed physical screen size
					}
				TSize winSize(screenSize);
				TPoint winPos;
				if (winSizeMode==1)
					{
					winSize.iWidth=winSize.iWidth*2/3;
					winSize.iHeight=winSize.iHeight*3/4;
					winPos.iX=(screenSize.iWidth-winSize.iWidth)/4;
					winPos.iY=(screenSize.iHeight-winSize.iHeight)*3/4;
					}
				testWin.SetExtent(winPos,winSize);
				TSize halfSize(winSize.iWidth/2,winSize.iHeight);
				TRect leftHalf(halfSize);
				TRect rightHalf(TPoint(halfSize.iWidth,0),halfSize);
				TRect leftEllipse(leftHalf);
				leftEllipse.Shrink(4,4);
				TRect rightEllipse(rightHalf);
				rightEllipse.Shrink(4,4);
				// Draw half the screen with redirection on, should only go to redirection test bitmap
				// Then draw again with redirection off, this time should go to the screen
				// The two steps are drawn with the color of the left/right rectangles swapped.
				for(TInt drawStep=0;drawStep<2;drawStep++)
					{
					TRgb leftColor;
					TRgb rightColor;
					if (drawStep==0)
						{
						leftColor=KRgbGreen;
						rightColor=KRgbRed;
						}
					else
						{ // Turn re-direction off for second time around loop
						iRedir->Redirect(CWsRedir::EFrontBuffer, EFalse);
						leftColor=KRgbRed;
						rightColor=KRgbGreen;
						}
					testWin.Invalidate();
					testWin.BeginRedraw();
					if (!drawInsideRedraw)
						testWin.EndRedraw();
					CWindowGc* testWinGc=TheClient->iGc;
					testWinGc->Activate(testWin);
					testWinGc->SetBrushColor(leftColor);
					testWinGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
					testWinGc->DrawRect(leftHalf);
					// Call CRP drawer to draw the coloured ellipses
					TheClient->iGc->DrawWsGraphic(wsGraphic1->Id(),leftEllipse);
					testWinGc->SetBrushColor(rightColor);
					testWinGc->DrawRect(rightHalf);
					TheClient->iGc->DrawWsGraphic(wsGraphic1->Id(),rightEllipse);
					testWinGc->Deactivate();
					if (drawInsideRedraw)
						testWin.EndRedraw();
					TheClient->iWs.Flush();
					}
				// We now check that the left rect of the re-directed drawing matches the right half
				// of the on-screen drawing
				CFbsBitmap* screenCopy=new(ELeave) CFbsBitmap;
				CleanupStack::PushL(screenCopy);
				User::LeaveIfError(screenCopy->Create(screenSize, EColor64K));
				TheClient->iScreen->CopyScreenToBitmap(screenCopy);
				match=CompareBitmapArea16Bpp(iFrontCopy,winPos,screenCopy,TPoint(winPos.iX+rightHalf.iTl.iX,winPos.iY),halfSize);
				TEST(match);
				if (!match)
					LOG_MESSAGE6(KLog,screenSize.iWidth,screenSize.iHeight,winSizeMode,redrawMode,modeIndex);
				// As a double check also check the right half of the off-screen drawing matches the
				// on-screen left half.
				match=CompareBitmapArea16Bpp(iFrontCopy,TPoint(winPos.iX+rightHalf.iTl.iX,winPos.iY),screenCopy,winPos,halfSize);
				TEST(match);
				if (!match)
					LOG_MESSAGE6(KLog,screenSize.iWidth,screenSize.iHeight,winSizeMode,redrawMode,modeIndex);
				CleanupStack::PopAndDestroy(screenCopy);
				}
			}
		}
 	CleanupStack::PopAndDestroy(3,wsGraphic1);
 	
	TEST(iNotify1->iResult);
	if(iNotify1->iResult==EFalse)
		{
		INFO_PRINTF1(iNotify1->iError);
		}
	TEST(iNotify2->iResult);
	if(iNotify1->iResult==EFalse)
		{
		INFO_PRINTF1(iNotify2->iError);
		}
	}

#endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA

/**
@SYMTestCaseID 		GRAPHICS-WSERV-0443

@SYMDEF     		INC109263

@SYMTestCaseDesc	TWindowServerEvent::NotifyDrawer can refer to a deleted array index causing a crash

@SYMTestPriority 	High

@SYMTestStatus		Implemented

@SYMTestActions		Cause an event that will generate the following behaviour through TWindowServerEvent::NotifyDrawer()
		
					The for loop performs the following:
					0) Drawer handler 1: Remove handle 1 ; 					Drawer handler 2: Do nothing
					1) Drawer handler 1: Remove handle 1,Add handle 1 ;		Drawer handler 2: Do nothing
					2) Drawer handler 1: Add handle 1 ; 					Drawer handler 2: Do nothing
					3) Drawer handler 1: Remove handle 2 ; 					Drawer handler 2: Do nothing
					4) Drawer handler 1: Remove handle 2,Add handle 2 ; 	Drawer handler 2: Do nothing
					5) Drawer handler 1: Add handle 2 ; 					Drawer handler 2: Do nothing
					6) Drawer handler 1: Remove handle 1,Remove handle 2 ; 	Drawer handler 2: Do nothing
			
					Repeat with handlers 1 and 2 swapped

@SYMTestExpectedResults		Loops through TWindowServerEvent::NotifyDrawer() should complete without crashing wserv
*/

void CTWsGraphs::TestNotifyRemoval()
	{
	_LIT(KTestEventNotification, "TestDrawerEventHandler");
	INFO_PRINTF1(KTestEventNotification);
	++iSubState;

	for (TInt ii = 0; ii<KNotifyDoNothing; ii++)
		{
		INFO_PRINTF2(_L("For loop %d"), ii);
		iNotify1->SetBehaviour(ii);					//Enable this plugin and set it to an event handling method
		iNotify2->SetBehaviour(KNotifyDoNothing);	//Add a second drawer handler which is enabled but does nothing
		CreateWindowL();							//Change visibility activating the event handlers - Fails if wserv crashes!
		iNotify1->SetBehaviour(KNotifyDisable);		//Disable plugin if still enabled
		iNotify2->SetBehaviour(KNotifyDisable);		//Disable plugin if still enabled
		DestroyWindowL();
		}
	INFO_PRINTF1(_L("Swap handlers"));
	for (TInt ii = 0; ii<KNotifyDoNothing; ii++)
		{
		INFO_PRINTF2(_L("For loop %d"), ii);
		iNotify2->SetBehaviour(KNotifyDoNothing);	//Add a first drawer handler which is enabled but does nothing
		iNotify1->SetBehaviour(ii);					//Enable this plugin and set it to an event handling method
		CreateWindowL();							//Change visibility activating the event handlers - Fails if wserv crashes!
		iNotify2->SetBehaviour(KNotifyDisable);		//Disable plugin if still enabled
		iNotify1->SetBehaviour(KNotifyDisable);		//Disable plugin if still enabled
		DestroyWindowL();
		}

	TEST(ETrue);		// If the test has failed WServ will have paniced.
	}

#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA
/**
@SYMTestCaseID           GRAPHICS-WSERV-0491
@SYMPREQ                 PREQ39
@SYMTestPriority         High
@SYMTestCaseDesc         Draw using a ECom-plugin which has direct access to the screen/OSB buffer 
@SYMTestActions          Create the plugin
						 Draw using the plugin
						 Update the position of the white line to line 70 and test
						 Update the position of the white line to line 80 and test
@SYMTestExpectedResults  White lines are drawn on the correct positions.
*/
void CTWsGraphs::TestMWsUiBufferL()
	{
	const TInt KWhiteLinePos = 70;
	const TRect KBlueRect(TPoint(50,50),TSize(100,100));
		
	// Construct and setup window to be drawn to
	RWindow window1 = RWindow(TheClient->iWs);
	CleanupClosePushL(window1);
    User::LeaveIfError(window1.Construct(*TheClient->iGroup->GroupWin(),ENullWsHandle));
    TSize winSize=TSize(TheClient->iScreen->SizeInPixels());
    window1.SetExtent(TPoint(0,0),winSize);
    window1.Activate();
    
	CWsBufferGraphic* graphic = CWsBufferGraphic::NewL();
	CleanupStack::PushL(graphic);
    
	// Draw inital drawing with a Crp which is blue rect and a white line at line 0
	TheGc->Activate(window1);
	TheGc->Clear();
	window1.BeginRedraw();
	TheGc->DrawWsGraphic(graphic->Id(),KBlueRect);
	window1.EndRedraw();
	TheGc->Deactivate();
	
    TheClient->iWs.Finish();
    User::After(2000000);
	
	// Update the position of the white line to line 70
	INFO_PRINTF1(_L("Update position of white line to line 70"));
	graphic->UpdateWhiteLinePos(KWhiteLinePos);
	TheClient->iWs.Finish();
	// Force some delays to wait until the line position changes
    User::After(2000000);
    //Test white line has been drawn and is in the correct postion
    TBool res1 = IsWhiteLine(KWhiteLinePos);
    TEST(res1);
    
	// Update the position of the white line to line 80
    INFO_PRINTF1(_L("Update position of white line to line 80"));
	graphic->UpdateWhiteLinePos(KWhiteLinePos+10);
	TheClient->iWs.Finish();
	// Force some delays to wait until the line position changes
	User::After(2000000);
	// Test white line has been drawn and is in the correct postion
    TBool res2 = IsWhiteLine(KWhiteLinePos+10);
    TEST(res2);
   
	graphic->Destroy();
	CleanupStack::PopAndDestroy(2, &window1);
	}

// Test whether a line is completely white
TBool CTWsGraphs::IsWhiteLine(TInt aWhiteLinePos)
	{
    TRgb color;
    TPoint pixel;
    
    for(TInt xPos = 0; xPos < TheClient->iScreen->SizeInPixels().iWidth; xPos++)
    	{
    	pixel = TPoint(xPos,aWhiteLinePos);
    	TheClient->iScreen->GetPixel(color,pixel);
    	if(color.Red() != 255 && color.Blue() != 255 && color.Green() != 255)
    		{
    		return EFalse;
    		}
    	}
    return ETrue;
	}
#endif //TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA

/**
	DoTestL() method, called by the WSERV Test Framework.
*/
void CTWsGraphs::RunTestCaseL(TInt /*aCurTestCase*/)
	{
	_LIT(KTest1,"DoTestWsGraphics");
	_LIT(KTest2,"DoTestOOMWsGraphics");
	_LIT(KTest3,"Interface Extension");
	_LIT(KTest4,"Screen Redirection");
	_LIT(KTest5,"TextCursor1");
	_LIT(KTest6,"TextCursor2");
	_LIT(KTest7,"Flicker Redirection");
	_LIT(KTest8,"Event Notification");
	_LIT(KTest9,"Successive Message");
	_LIT(KTest10,"Redirection Using WsBackBuffer");
	_LIT(KTest11,"Group Change");
	_LIT(KTest12,"Frame Rate");
	_LIT(KTest13,"Leak In Service");
	_LIT(KTest14,"Add/Swap GDArray");
	_LIT(KTest15,"Nested Drawer CRP");
	_LIT(KTest16,"Notify Removal");
	_LIT(KTest17,"Screen Mode Change");
	_LIT(KTest18,"UI Buffer");
	_LIT(KTest19,"Graphics Drawer Coverage");
	CFbsBitmap bitmap1;
	CFbsBitmap mask1;
	CWsGraphicBitmap* bTest=NULL;
	TSize screenSize=TheClient->iScreen->SizeInPixels();

	bitmap1.Create(screenSize,TheClient->iScreen->DisplayMode());
	mask1.Create(screenSize,TheClient->iScreen->DisplayMode());
	((CTWsGraphsStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);

	switch(++iTest->iState)
		{
	case 1:
/**
	@SYMTestCaseID	GRAPHICS-WSERV-0528
*/
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0528"));
		// Launch new process with PROTSERV capability to run CWSGraphics tests in
		iTest->LogSubTest(KTest1);
		// This process only launches succesfully when _DEBUG is defined for the build, because it depends
		// on the existance of debug macros such as _UHEAP_MARK, _UHEAP_MARKEND, _UHEAP_FAILNEXT, ... etc
		LaunchNewProcess(KTestExe);
		break;
	case 2:
		{
		/**
   		@SYMTestCaseID GRAPHICS-WSERV-0017

		@SYMPREQ	PREQ1246

		@SYMDEF		DEF081259

		@SYMTestCaseDesc Out of memery test when creating a CWsGraphic.

		@SYMTestPriority High

		@SYMTestStatus Implemented

		@SYMTestActions Out of memory test when creating a CWsGraphic.

		@SYMTestExpectedResults Whenever an API call fails, it should leave the number
				of allocated heap cells unchanged.
		*/
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0017"));

		iTest->LogSubTest(KTest2);
		TInt failRate;
		for(failRate=1;;failRate++)
			{
			__UHEAP_RESET;
			__UHEAP_SETFAIL(RHeap::EDeterministic,failRate);
			__UHEAP_MARK;

			TRAPD(ret,bTest=CWsGraphicBitmap::NewL(&bitmap1,&mask1));
			TEST((ret==KErrNone || ret==KErrNoMemory));
			if (ret!=KErrNone && ret!=KErrNoMemory)
				{
				_LIT(KLog,"Failed to create CWsGraphicBitmap  error=%d");
				LOG_MESSAGE2(KLog,ret);
				}
			if (ret!=KErrNone)
				{
				__UHEAP_MARKEND;
				}
			else
				{
				TEST(bTest!=NULL);
				if (bTest==NULL)
					{
					_LIT(KLog,"Object creation didn't leave but returned NULL");
					LOG_MESSAGE(KLog);
					}
				delete bTest;
				bTest=NULL;
				__UHEAP_MARKEND;
				TLogMessageText logMessageText;
				_LIT(KSet,"OOM test succeds after %d allocations.");
				logMessageText.Format(KSet,failRate);
				LOG_MESSAGE(logMessageText);
				break;
				}
			}
		__UHEAP_RESET;
		}
		break;
	case 3:
		iTest->LogSubTest(KTest3);
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0371"));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
			
			if (TestInterfaceExtensionL()==EWait)
				--iTest->iState;
#endif
		break;
	case 4:
		iTest->LogSubTest(KTest4);
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0372"));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA			
			if (TestScreenRedirectionL()==EWait)
				--iTest->iState;
#endif
		break;
	case 5:
		iTest->LogSubTest(KTest5);
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0363"));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA	
			if (TestTextCursorUnderRedirectionL(ETestStandardTextCursor) == EWait)
				--iTest->iState;
#endif
		break;
	case 6:
		iTest->LogSubTest(KTest6);
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0363"));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA	
			if (TestTextCursorUnderRedirectionL(ETestCustomTextCursor) == EWait)
				--iTest->iState;
#endif
		break;
	case 7:
		iTest->LogSubTest(KTest7);
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0376"));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA			
			if (TestFlickerRedirectionL()==EWait)
				--iTest->iState;
#endif
		break;
	case 8:
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0378"));
		iTest->LogSubTest(KTest8);
		if (TestEventNotificationL()==EWait)
			--iTest->iState;
		break;
	case 9:
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0381"));
		iTest->LogSubTest(KTest9);
		if (TestSuccessiveMessageL()==EWait)
			--iTest->iState;
		break;
	case 10:
		iTest->LogSubTest(KTest10);
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0527"));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
		if(TestRedirectionUsingWsBackBufferL()==EWait)
			--iTest->iState;
#endif
		break;
	case 11:
/**
	@SYMTestCaseID	GRAPHICS-WSERV-0529
*/
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0529"));
		iTest->LogSubTest(KTest11);
		if(TestWindowGroupChangeL()==EWait)
			--iTest->iState;
		break;
	case 12:
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0382"));
		iTest->LogSubTest(KTest12);
		if(TestFrameRateL()==EWait)
			--iTest->iState;
		break;
	case 13:
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-LeakInService-0001"));
		iTest->LogSubTest(KTest13);
		DoTestLeakInServiceL();
		break;
	case 14:
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-NegAddSwapGDArray-0001"));
		iTest->LogSubTest(KTest14);
		TestAddSwapGDArrayL();
		break;
	case 15:
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0438"));
		iTest->LogSubTest(KTest15);
		TestNestedDrawerCRP();
		break;
	case 16:
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0443"));
		iTest->LogSubTest(KTest16);
		TestNotifyRemoval();
		break;
	case 17:
		iTest->LogSubTest(KTest17);
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0530"));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
/**
	@SYMTestCaseID	GRAPHICS-WSERV-0530
*/
			
			TestScreenModeChangeL();
#endif
		break;
	case 18:
		iTest->LogSubTest(KTest18);
		((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0491"));
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA
			
			TestMWsUiBufferL();
#endif
			break;
		case 19:
			iTest->LogSubTest(KTest19);
/**
	@SYMTestCaseID	GRAPHICS-WSERV-0531
*/
			((CTWsGraphsStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0531"));
			TestGraphicDrawerCoverage();
			break;
		default:
			((CTWsGraphsStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
			((CTWsGraphsStep*)iStep)->CloseTMSGraphicsStep();
			TestComplete();
			break;
		}
	((CTWsGraphsStep*)iStep)->RecordTestResultL();
	}

__WS_CONSTRUCT_STEP__(WsGraphs)