windowing/windowserver/test/tauto/TWSGRAPHS.CPP
branchRCL_3
changeset 163 bbf46f59e123
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/tauto/TWSGRAPHS.CPP	Tue Aug 31 16:31:06 2010 +0300
@@ -0,0 +1,2593 @@
+// 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)