diff -r 000000000000 -r 5d03bc08d59c windowing/windowserver/tauto/AUTO.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/windowing/windowserver/tauto/AUTO.CPP Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,2543 @@ +// Copyright (c) 1995-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: +// Automatically test the window server +// +// + + +#include +#include +#include +#include +#include "../tlib/testbase.h" +#include +#include "AUTO.H" + +LOCAL_D const TUint KPanicThreadHeapSize=0x8000; + +GLREF_C TInt ProcPriTestOtherProcess(TAny *aScreenNumber); +GLREF_C TInt ProcToKill(TAny *aScreenNumber); +GLREF_C TInt ProcDirect(TAny *aScreenNumber); +GLREF_C TInt ProcMultiDisplay(TAny *aScreenNumber); + +_LIT(Priority,"ProcPriTest"); +_LIT(ToKill,"ProcToKill"); +_LIT(Direct,"ProcDirect"); +_LIT(MultiDisplay,"ProcMultiDisplay"); + +CProcess::TInitialFunction CProcess::iFunctions[]= + { + TInitialFunction(Priority,ProcPriTestOtherProcess), + TInitialFunction(ToKill,ProcToKill), + TInitialFunction(Direct,ProcDirect), + TInitialFunction(MultiDisplay,ProcMultiDisplay) + }; + +GLDEF_D TestWindow *BaseWin; +GLDEF_D TestWindow *TestWin; +GLDEF_D TestClient *TheClient=NULL; +GLDEF_D CWindowGc *TheGc; +TInt CTestBase::iMaxGrays=0; +TInt CTestBase::iScreenNo=0; +TInt CTestBase::iMaxColors=0; +TInt CTestBase::iNumberTestsPass=0; +TInt CTestBase::iNumberTests=0; +TRect CTestBase::iNormalPointerCursorArea; +TPartialRedrawType CTestBase::iRedrawType=EPartialRedraw_Unknown; +TInt CTestBase::iNumberOfGrpWndsOnPrimaryScreenWithZeroPriority = 0; +TInt CTestDriver::iTestNum=0; + +GLDEF_D TInt TheTestResult=ETestPassed; // start with passed to anticipate empty test table + +const TInt KBorderWinWidth = 5; + +_LIT(Auto,"AUTO "); + +TInt64 TTestRects::iSeed=0; +TRect TTestRects::iList[]={ +// 0-5 + TRect(2,2,2,2), + TRect(2,2,2,2), + TRect(2,2,2,2), + TRect(2,2,2,2), + TRect(2,2,2,2), +// 5-13 + TRect(0,0,0,0), + TRect(2,0,2,0), + TRect(4,0,4,0), + TRect(0,2,0,2), + TRect(2,2,2,2), + TRect(4,2,4,2), + TRect(0,4,0,4), + TRect(2,4,2,4), + TRect(4,4,4,4), +// 13-22 + TRect(0,0,1,1), + TRect(1,0,3,1), + TRect(3,0,4,1), + TRect(0,1,1,3), + TRect(1,1,3,3), + TRect(3,1,4,3), + TRect(0,3,1,4), + TRect(1,3,3,4), + TRect(3,3,4,4), +// 23-31 + TRect(0,0,2,0), + TRect(2,0,4,0), + TRect(0,0,4,0), + TRect(0,2,2,2), + TRect(2,2,4,2), + TRect(0,2,4,2), + TRect(0,4,2,4), + TRect(2,4,4,4), + TRect(0,4,4,4), +// 32-40 + TRect(0,0,0,2), + TRect(0,2,0,4), + TRect(0,0,0,4), + TRect(2,0,2,2), + TRect(2,2,2,4), + TRect(2,0,2,4), + TRect(4,0,4,2), + TRect(4,2,4,4), + TRect(4,0,4,4), +// 41-44 + TRect(0,0,2,2), + TRect(2,0,4,2), + TRect(0,2,2,4), + TRect(2,2,4,4), +// 45-48 + TRect(0,0,3,3), + TRect(1,0,4,3), + TRect(0,1,3,4), + TRect(1,1,4,4), +// 49 + TRect(0,0,4,4), +// 40-53 + TRect(1,2,2,2), + TRect(2,2,3,2), + TRect(2,1,2,2), + TRect(2,2,3,2), +// 54-59 + TRect(1,2,3,2), + TRect(2,1,2,3), + TRect(1,1,2,2), + TRect(1,2,2,3), + TRect(2,2,3,3), + TRect(2,1,3,2), +// 60-63 + TRect(1,1,3,2), + TRect(1,1,2,3), + TRect(1,2,3,3), + TRect(2,1,3,3)}; + +#if defined(__WINS__) +void FindNonMatchingPixelL(TPoint aPt1,TPoint aPt2,TSize aSize) +// This function is purely for use when debugging to find the first non-matching pixel +// when a check of two on screen rects has failed. + { + HBufC8* buf1=HBufC8::NewMaxLC(2*aSize.iWidth); + HBufC8* buf2=HBufC8::NewMaxLC(2*aSize.iWidth); + TPtr8 ptr1=buf1->Des(); + TPtr8 ptr2=buf2->Des(); + TInt row=0; + TBool ret = true; + for (;rowiScreen->GetScanLine(ptr1,aPt1,aSize.iWidth,EColor64K); + TheClient->iScreen->GetScanLine(ptr2,aPt2,aSize.iWidth,EColor64K); + if (ptr1!=ptr2) + break; + ++aPt1.iY; + ++aPt2.iY; + } + TRgb color1,color2; + if (rowiScreen->GetPixel(color1,aPt1); + TheClient->iScreen->GetPixel(color2,aPt2); + if (color1!=color2) + { // Break here to find first pixel that didn't match. + TBuf<256> buf; + _LIT(KFindNonMatchingPixelFmt,"First non matching pixel (%d,%d)"); + buf.Format(KFindNonMatchingPixelFmt,col,row); + TheClient->iWs.LogMessage(buf); + break; + + } + ++aPt1.iX; + ++aPt2.iX; + } + } + CleanupStack::PopAndDestroy(2); + } + +void FindNonMatchingPixel(TPoint aPt1,TPoint aPt2,TSize aSize) + { + TRAPD(ignore,FindNonMatchingPixelL(aPt1,aPt2,aSize)); + } +#endif + +void AutoPanic(TInt aPanic) + { + User::Panic(_L("Auto"),aPanic); + } + +void CleanUpWindow(TAny *aWindow) + { + ((RWindowTreeNode *)aWindow)->Close(); + } + +void PushWindowL(RWindowTreeNode *aWindow) + { + CleanupStack::PushL(TCleanupItem(CleanUpWindow,aWindow)); + } + + +TBool OpacityAndAlphaSupportedL() + { + // If opacity is not implemented, EFalse will be returned + if(TransparencySupportedL()!=KErrNone) + return EFalse; + + const TRgb KTransparencyColor(0,0,0); + RWindow winb(TheClient->iWs); + CleanupClosePushL(winb); + RWindow wint(TheClient->iWs); + CleanupClosePushL(wint); + User::LeaveIfError(winb.Construct(*TheClient->iGroup->GroupWin(), ENullWsHandle)); + User::LeaveIfError(wint.Construct(*TheClient->iGroup->GroupWin(), ENullWsHandle)); + winb.SetExtent(TPoint(0,0), TSize(50,50)); + wint.SetExtent(TPoint(0,0), TSize(50,50)); + winb.SetRequiredDisplayMode(EColor256); + wint.SetRequiredDisplayMode(EColor256); + wint.SetTransparencyFactor(KTransparencyColor); + winb.SetBackgroundColor(TRgb(0,0,255)); + wint.SetBackgroundColor(TRgb(255,0,0)); + winb.Activate(); + wint.Activate(); + + wint.BeginRedraw(); + TheClient->iGc->Activate(wint); + TheClient->iGc->SetOpaque(ETrue); + TheClient->iGc->SetPenStyle(CGraphicsContext::ENullPen); + TheClient->iGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + TheClient->iGc->SetBrushColor(TRgb(0,255,0)); + TheClient->iGc->DrawRect(TRect(TPoint(0,0), TSize(50,50))); + TheClient->iGc->SetOpaque(EFalse); + TheClient->iGc->Deactivate(); + wint.EndRedraw(); + TheClient->Flush(); + + // The window should be all green, if opacity is working, or all blue if it isn't. + // If the window has any other colour, then something has broken. + TRgb color; + TheClient->iScreen->GetPixel(color,TPoint(25,25)); + if (color.Red()>0 || ((color.Green()==0) == (color.Blue()==0))) + User::Leave(KErrGeneral); + TBool ret=(color.Green()>0); + + CleanupStack::PopAndDestroy(2,&winb); // wint + return ret; + } + +TInt TransparencySupportedL() + { + // Creates a window and enables alpha transparency, if this feature + // is not enabled, KErrNotSupported will be returned + RWindow win(TheClient->iWs); + User::LeaveIfError(win.Construct(*TheClient->iGroup->GroupWin(), ENullWsHandle)); + win.SetExtent(TPoint(0,0), TSize(50,50)); + TInt ret=win.SetTransparencyAlphaChannel(); + win.Close(); + return ret; + } + +TInt CheckScalingSupportedOrNot() + { + TBool scalingSupported=EFalse; + TSizeMode originalModeData=TheClient->iScreen->GetCurrentScreenModeAttributes(); + TSizeMode tempData=originalModeData; + tempData.iScreenScale=TSize(2,2); + TheClient->iScreen->SetCurrentScreenModeAttributes(tempData); + TSize scale=TheClient->iScreen->GetCurrentScreenModeScale(); + if (scale.iWidth==2 && scale.iHeight==2) + { + scalingSupported=ETrue; + } + TheClient->iScreen->SetCurrentScreenModeAttributes(originalModeData); + TheClient->Flush(); + return scalingSupported; + } + +TBool CheckNonZeroOriginsSupportedOrNot() + { + TBool nonZeroOriginsSupported=EFalse; + TSizeMode sizeMode1=TheClient->iScreen->GetCurrentScreenModeAttributes(); + TSizeMode sizeMode2=sizeMode1; + sizeMode2.iOrigin=TPoint(30,30); + TheClient->iScreen->SetCurrentScreenModeAttributes(sizeMode2); + TPoint origin=TheClient->iScreen->GetCurrentScreenModeScaledOrigin(); + if (origin.iX==30 && origin.iY==30) + { + nonZeroOriginsSupported=ETrue; + } + TheClient->iScreen->SetCurrentScreenModeAttributes(sizeMode1); + TheClient->Flush(); + return nonZeroOriginsSupported; + } + +TPoint PhysicalToLogical(TPoint aPhysicalPtMinusOrigin,TSize aScale) + { + TPoint logicalPt(aPhysicalPtMinusOrigin); + if (aScale.iWidth!=1) + { + logicalPt.iX=(logicalPt.iX>= 0 ? logicalPt.iX/aScale.iWidth : (logicalPt.iX-(aScale.iWidth-1))/aScale.iWidth); + } + if (aScale.iHeight!=1) + { + logicalPt.iY=(logicalPt.iY>= 0 ? logicalPt.iY/aScale.iHeight : (logicalPt.iY-(aScale.iHeight-1))/aScale.iHeight); + } + return logicalPt; + } + +// +// Log window, logs testing // +// + +LogWindow::LogWindow() : CTWin(), iTestTitle(KNullDesC), iSubTitle(KNullDesC), iMessage(KNullDesC) + {} + +void LogWindow::ConstructL(CTWinBase &parent) + { + CTWin::ConstructL(parent); + iTitleHeight=iFont->HeightInPixels()+4; + } + +void LogWindow::DrawSubTitle() + { + iGc->DrawText(iSubTitle, TRect(2,iTitleHeight*2,iSize.iWidth-2,iTitleHeight*3),iFont->AscentInPixels(), CGraphicsContext::ECenter); + } + +void LogWindow::DrawMessage() + { + iGc->DrawText(iMessage, TRect(1,iTitleHeight*4,iSize.iWidth-2,iTitleHeight*5),iFont->AscentInPixels(), CGraphicsContext::ECenter); + } + +void LogWindow::Draw() + { + iGc->SetPenColor(TRgb::Gray16(8)); + iGc->SetPenColor(TRgb::Gray16(0)); + DrawBorder(); + iGc->DrawLine(TPoint(0,iTitleHeight),TPoint(iSize.iWidth,iTitleHeight)); + iGc->DrawText(iTestTitle, TPoint((iSize.iWidth-iFont->TextWidthInPixels(iTestTitle))/2,iFont->AscentInPixels()+2)); + DrawSubTitle(); + DrawMessage(); + } + +/** +This function is not used at the moment but I leave it in in case I need it when I improve the logging in +the log window. +*/ +void LogWindow::LogTest(const TDesC &aTitle,TInt aNum) + { + _LIT(Test,"Test %d,%S"); + iTestTitle.Format(Test,aNum,&aTitle); + TLogMessageText buf; + _LIT(AutoNewTest,"AUTO New Test: "); + buf.Append(AutoNewTest); + buf.Append(iTestTitle); + TheClient->LogMessage(buf); + iMessage.Zero(); + iWin.Invalidate(); + } + +/** +This function is not used at the moment but I leave it in in case I need it when I improve the logging in +the log window. +*/ +const TDesC& LogWindow::LogSubTest(const TDesC &aTitle,TInt aNum) + { + _LIT(SubTest,"Sub-Test[%d], %S"); + iSubTitle.Format(SubTest,aNum,&aTitle); + TLogMessageText buf; + buf.Append(Auto); + buf.Append(iSubTitle); + TheClient->LogMessage(buf); + iMessage.Zero(); + iGc->Activate(iWin); + iGc->UseFont((CFont *)iFont); + iGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + DrawSubTitle(); + DrawMessage(); + iGc->Deactivate(); + TheClient->iWs.Flush(); + return iSubTitle; + } + +const TDesC& LogWindow::LogMessage(TBool aLog,const TDesC& aText,TInt aNum) + { + if (aNum!=EDummyValue) + { + _LIT(StringInt,"%S %d"); + iMessage.Format(StringInt,&aText,aNum); + } + else + { + _LIT(String,"%S"); + iMessage.Format(String,&aText); + } + iGc->Activate(iWin); + iGc->UseFont((CFont *)iFont); + iGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + DrawMessage(); + iGc->Deactivate(); + if (aLog) + { + TLogMessageText buf; + buf.Append(Auto); + buf.Append(iMessage); + TheClient->LogMessage(buf); + } + TheClient->iWs.Flush(); + return iMessage; + } + + +// +// Test window, simple window used to do test graphics in // +// +TestWindow::TestWindow() : CTWin() + { + } + +TestWindow::~TestWindow() + { + delete iBorderWin; + } + +void TestWindow::SetUpL(TPoint pos,TSize size,CTWinBase *parent, CWindowGc &aGc) + { + iBorderWin=new(ELeave) CBorderWindow(); + iBorderWin->SetUpL(pos,size,parent,aGc); + TRAPD(err, CTWin::ConstructL(*iBorderWin)); + if (err==KErrNone) + { + SetExt(TPoint(2,2),TSize(size.iWidth-4,size.iHeight-4)); + if (err==KErrNone) + { + Activate(); + AssignGC(aGc); + return; + } + } + delete this; + User::Leave(err); + } + +void TestWindow::Draw() + { + iGc->Clear(); + } + +void TestWindow::ClearWin() + { + TheGc->Activate(*Win()); + TheGc->Clear(); + TheGc->Deactivate(); + } + +void TestWindow::SetBorderExt(TPoint aPos, TSize aSize) + { + iBorderWin->SetExt(aPos, aSize); + } + +CBorderWindow* TestWindow::GetBorderWin() + { + return iBorderWin; + } +// +CBorderWindow::CBorderWindow() : CTWin() + { + } + +void CBorderWindow::ConstructL(CTWinBase &parent) + { + CTWin::ConstructL(parent); + } + +void CBorderWindow::Draw() + { + iGc->SetBrushColor(TRgb::Gray16(0)); + iGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + iGc->SetPenStyle(CGraphicsContext::ENullPen); + iGc->DrawRect(TRect(Size())); + } + +// + +TestWindowGroup::TestWindowGroup(CTClient *aClient) : CTWindowGroup(aClient) + { + } + +void TestWindowGroup::BecomeOwning() + { + iGroupWin.DefaultOwningWindow(); + } + +void TestWindowGroup::KeyL(const TKeyEvent &aKey,const TTime &aTime) + { + if (aKey.iModifiers&EModifierFunc) + { + switch(aKey.iCode) + { + case 'f': + TheClient->Driver()->iTest->TriggerFail(); + break; + } + } + else if (iCurWin) + iCurWin->WinKeyL(aKey,aTime); + } + +void TestWindowGroup::KeyDownL(const TKeyEvent &aKey,const TTime &aTime) + { + if (iCurWin) + iCurWin->KeyDownL(aKey,aTime); + } + +void TestWindowGroup::KeyUpL(const TKeyEvent &aKey,const TTime &aTime) + { + if (iCurWin) + iCurWin->KeyUpL(aKey,aTime); + } + +// + +TestClient::TestClient() + {} + +void TestClient::ConstructL() + { + CTClient::ConstructL(); + + iGroup=new(ELeave) TestWindowGroup(this); + iGroup->ConstructL(); + + iScreen->GetScreenSizeModeList(&iScreenModes); + iScreen->SetScreenMode(iScreenModes[0]); + TSize screenSize=iScreen->SizeInPixels(); + + TInt winWidth=(screenSize.iWidth/3)-10; + TInt winHeight=screenSize.iHeight-10; + iStdLogWindow=new(ELeave) LogWindow(); + iStdLogWindow->SetUpL(TPoint(5,5),TSize(winWidth,winHeight),iGroup,*iGc); + BaseWin=new(ELeave) TestWindow(); + BaseWin->SetUpL(TPoint(screenSize.iWidth/3+5,5),TSize(winWidth,winHeight),iGroup,*iGc); + TestWin=new(ELeave) TestWindow(); + TestWin->SetUpL(TPoint(screenSize.iWidth/3*2+5,5),TSize(winWidth,winHeight),iGroup,*iGc); + + iDriver = CTestDriver::CreateL(iScreenNumber); // virtual constructor + + TheGc=new(ELeave) CWindowGc(iScreen); + User::LeaveIfError(TheGc->Construct()); + + _LIT(KTestLog,"WSERV Auto Test Log"); + LogMessage(KTestLog()); + LogAvailableScreenModeL(); + + //This class was designed to be created once and reused by all the tests, now it is created for each test, + //this needs to be changed back so tests like the following are only done once. + TestWsSetBufferSizeL(); + TestWsSetMaxBufferSizeL(); + } + +inline CTestDriver* TestClient::Driver() + { + return iDriver; + } + +TBool TestClient::WaitForEvent() + { + if (iEventHandler->iStatus!=KRequestPending) + return ETrue; + else if (iRedrawEventHandler->iStatus!=KRequestPending) + return EFalse; + User::WaitForRequest(iEventHandler->iStatus,iRedrawEventHandler->iStatus); + TRequestStatus* status=&iEventHandler->iStatus; + TBool ret=ETrue; + if (iEventHandler->iStatus==KRequestPending) + { + status=&iRedrawEventHandler->iStatus; + ret=EFalse; + } + TInt reason=status->Int(); + *status=KRequestPending; + User::RequestComplete(status,reason); + return ret; + } + +TBool TestClient::IsEventWaiting() + { + return (iEventHandler->iStatus!=KRequestPending || iRedrawEventHandler->iStatus!=KRequestPending); + } + +TestClient::~TestClient() + { + iScreenModes.Close(); + delete iDriver; + delete TheGc; + delete iStdLogWindow; + delete BaseWin; + delete TestWin; + } + +void TestClient::LogAvailableScreenModeL() + { + _LIT(KColorModes,"Color Modes: "); + _LIT(KComma,", "); + _LIT(KColor,"Color"); + _LIT(KGrey,"Grey"); + CArrayFixFlat* modeList=new(ELeave) CArrayFixFlat(15); + iWs.GetColorModeList(modeList); + TLogMessageText buf,buf2; + buf.Append(KColorModes); + TDisplayMode mode; + TInt ii=0; + FOREVER + { + mode=STATIC_CAST(TDisplayMode,(*modeList)[ii]); + buf.AppendNum((*modeList)[ii]); + buf2.Append(TDisplayModeUtils::IsDisplayModeColor(mode)?KColor():KGrey()); + buf2.AppendNum(TDisplayModeUtils::NumDisplayModeColors(mode)); + if (mode==EColor16MU) + buf2.Append('U'); + if (++ii==modeList->Count()) + break; + buf.Append(KComma); + buf2.Append(KComma); + } + LogMessage(buf); + LogMessage(buf2); + delete modeList; + } + +void TestClient::TestWsSetBufferSizeL() + { + RWsSession ws; + User::LeaveIfError(ws.Connect()); + ws.SetBufferSizeL(256); // default buffer size 640 + ws.SetBufferSizeL(0x8000); // 16K is max buffer size + ws.SetBufferSizeL(0x4000); + ws.Close(); + } + +void TestClient::TestWsSetMaxBufferSizeL() + { + RWsSession ws; + User::LeaveIfError(ws.Connect()); + // allow buffer to grow bigger than the default 640 bytes + const TInt KBigMessageSize = 800; + ws.SetMaxBufferSizeL(KBigMessageSize + 8); // big message + command header length + + // send the big message to the wserv + TBuf8 bigMessage; + + // LogMessage needs a pointer to a TInt with the message size at the start of the buffer + const TInt szLength = sizeof(TInt); + TInt length = KBigMessageSize - szLength; // length in Unicode characters + bigMessage.Append((TUint8*) &length, szLength); + + _LIT(KLetterA, "a"); + do + { + bigMessage.Append((TUint8*) KLetterA().Ptr(), 2); + } + while (bigMessage.Length() < KBigMessageSize); + + // send to Wserv, note that the message is too long to be logged + ws.TestWrite(ws.WsHandle(), EWsClOpLogMessage, bigMessage.Ptr(), KBigMessageSize); + ws.Flush(); + + ws.Close(); + } + +void TestClient::SetTestClientScreenMode(TInt aMode) + { + iScreen->SetAppScreenMode(aMode); + iScreen->SetScreenMode(aMode); + UpdateTestClientScreenMode(); + } + +void TestClient::UpdateTestClientScreenMode() + { + TSize screenSize=iScreen->SizeInPixels(); + + // Sets new positions and dimensions for the three window and their controlling border windows + + if (screenSize.iHeight > screenSize.iWidth) // Portrait mode + { + TInt winWidth=screenSize.iWidth - (KBorderWinWidth * 2); + TInt winHeight=(screenSize.iHeight/3) - (KBorderWinWidth * 2); + + iStdLogWindow->SetExt(TPoint(KBorderWinWidth,KBorderWinWidth),TSize(winWidth,winHeight)); + BaseWin->SetBorderExt(TPoint(KBorderWinWidth,screenSize.iHeight/3+KBorderWinWidth),TSize(winWidth,winHeight)); + BaseWin->SetExt(TPoint(2,2),TSize(winWidth - (KBorderWinWidth - 1),winHeight - (KBorderWinWidth - 1))); + TestWin->SetBorderExt(TPoint(KBorderWinWidth,screenSize.iHeight/3*2+KBorderWinWidth),TSize(winWidth,winHeight)); + TestWin->SetExt(TPoint(2,2),TSize(winWidth - (KBorderWinWidth - 1),winHeight - (KBorderWinWidth - 1))); + } + else // Landscape modes + { + TInt winWidth=(screenSize.iWidth/3) - (KBorderWinWidth * 2); + TInt winHeight=screenSize.iHeight - (KBorderWinWidth * 2); + + iStdLogWindow->SetExt(TPoint(KBorderWinWidth,KBorderWinWidth),TSize(winWidth,winHeight)); + BaseWin->SetBorderExt(TPoint(screenSize.iWidth/3 + KBorderWinWidth,KBorderWinWidth),TSize(winWidth,winHeight)); + BaseWin->SetExt(TPoint(2,2),TSize(winWidth - (KBorderWinWidth - 1),winHeight - (KBorderWinWidth - 1))); + TestWin->SetBorderExt(TPoint(screenSize.iWidth/3*2+KBorderWinWidth,KBorderWinWidth),TSize(winWidth,winHeight)); + TestWin->SetExt(TPoint(2,2),TSize(winWidth - (KBorderWinWidth - 1),winHeight - (KBorderWinWidth - 1))); + } + + // Remove shading artefacts from window resizing operations + TestWin->Win()->Invalidate(); + TestWin->Win()->BeginRedraw(); + TestWin->ClearWin(); + TestWin->Win()->EndRedraw(); + + BaseWin->Win()->Invalidate(); + BaseWin->Win()->BeginRedraw(); + BaseWin->ClearWin(); + BaseWin->Win()->EndRedraw(); + + TheClient->iWs.Flush(); + } + + +// +// TestDriver, drives the test code // +// +CTestDriver* CTestDriver::CreateL(TInt aScreenNumber) + { + CTestDriver* self = NULL; + if (aScreenNumber==KDefaultScreen) + self = new (ELeave) CTestDriverPrimary(aScreenNumber); + else + self = new (ELeave) CTestDriverSecondary(aScreenNumber); + + return self; + } + +CTestDriver::CTestDriver(TInt aScreenNumber) + : iScreenNumber(aScreenNumber) + { + iStartTime.HomeTime(); + HAL::Get(HALData::EDisplayNumberOfScreens, iNumberOfScreens); + } + +CTestDriver::~CTestDriver() + { + } + +void CTestDriver::DestroyTest() + { + delete iTest; + iTest=NULL; + } + +void CTestDriver::TestComplete2() + { + ++iTestNum; + if (iTestNum==iTestSize) + { + TBuf<64> timeBuf; + TTime endTime; + endTime.HomeTime(); + TTimeIntervalMicroSeconds elapseTime=endTime.MicroSecondsFrom(iStartTime); + TInt64 elapseTime2=elapseTime.Int64()/1000; + TUint diffi = I64LOW(elapseTime2); + _LIT(TestPass,"PASSED"); + _LIT(TestFail,"FAILED"); + TInt noOfTests=CTestBase::iNumberTests; + TInt noOfTestsPass=CTestBase::iNumberTestsPass; + _LIT(TimeBuf,"Elapse Time %d:%02d.%03d %S"); + timeBuf.Format(TimeBuf,diffi/60000,(diffi/1000)%60,diffi%1000000,&(noOfTests==noOfTestsPass?TestPass:TestFail)); + TBuf<60> testReport; + _LIT(Checks,"Checks"); + _LIT(Fails,"Fails"); + _LIT(TestReport,"Tests:%d %S:%d"); + TInt testNumber=(noOfTests==noOfTestsPass? noOfTestsPass : noOfTests-noOfTestsPass); + testReport.Format(TestReport,iTestNum,&(noOfTests==noOfTestsPass?Checks():Fails()),testNumber); + if (noOfTests!=noOfTestsPass) + { + _LIT(NumTests,"/%d"); + testReport.AppendFormat(NumTests,noOfTests); + } + + TBuf<60> logTestReport; + _LIT(LogReport," %S:%d/%d"); + logTestReport.Format(LogReport,&Checks,noOfTestsPass,noOfTests); + TLogMessageText buf; + _LIT(Finished,"AUTO Testing Complete, "); + buf.Append(Finished); + buf.Append(timeBuf); + buf.Append(logTestReport); + TheClient->LogMessage(buf); + + TheTestResult = noOfTests==noOfTestsPass? ETestPassed : ETestFailed; + DoDisplayDialog(timeBuf,testReport); + } + } + +// +// Test driver for primary screen (has digitiser/pointer) +// +CTestDriverPrimary::CTestDriverPrimary(TInt aScreenNumber) : CTestDriver(aScreenNumber) + { + TInt i; + TInt numOfEntries = 1; + for (i=0; i1); + if (aTl>aBr) + { + TInt tmp=aBr; + aBr=aTl; + aTl=tmp; + } + } + +TRect TTestRects::operator[](TInt aIndex) + { + TRect rect; + if (aIndexiTl.iX==pRect->iBr.iX) + RectCoordPair(rect.iTl.iX,rect.iBr.iX,pRect->iTl.iX,iSize.iWidth); + else + { + rect.iTl.iX=RectCoord(pRect->iTl.iX,iSize.iWidth); + rect.iBr.iX=RectCoord(pRect->iBr.iX,iSize.iWidth); + } + if (pRect->iTl.iY==pRect->iBr.iY) + RectCoordPair(rect.iTl.iY,rect.iBr.iY,pRect->iTl.iY,iSize.iHeight); + else + { + rect.iTl.iY=RectCoord(pRect->iTl.iX,iSize.iHeight); + rect.iBr.iY=RectCoord(pRect->iBr.iX,iSize.iHeight); + } + } + else if (aIndexConstructL(aHandle, aSizeInPixels, aDispMode); + return self; + } + +void CBitmap::ConstructL(TInt aHandle,const TSize& aSizeInPixels,TDisplayMode aDispMode) + { + iBitmap=new(ELeave) CFbsBitmap(); + if (aHandle==0) + { + User::LeaveIfError(iBitmap->Create(aSizeInPixels,aDispMode)); + } + else + { + User::LeaveIfError(iBitmap->Duplicate(aHandle)); + } + iDevice=CFbsBitmapDevice::NewL(iBitmap); + User::LeaveIfError(iDevice->CreateContext(iGc)); + } + +CBitmap::~CBitmap() + { + delete iGc; + delete iDevice; + delete iBitmap; + } + + +// CTestBase // + +CTestBase::CTestBase(const TDesC& aTitle,CTWsGraphicsBase* aTestBase) + { + iTestBase=aTestBase; + iTitle.Copy(aTitle); + + iScreenNo = iTestBase->GetScreenFromIni(); + + TheClient=new(ELeave) TestClient(); + + if (CTestBase::iScreenNo == 1) + { + TheClient->SetScreenNumber(1); + iScreenNumber = 1; + } + else + { + TheClient->SetScreenNumber(0); + iScreenNumber = 0; + } + + if (iScreenNumber == 1) + { + iMinWin = new(ELeave) CMinWin(iScreenNumber); + iMinWin->ConstructL(); + } + + iTestNum=CTestDriver::iTestNum; + TheClient->ConstructL(); + TheClient->StdLogWindow().LogTest(iTitle,iTestNum); + iDriver=TheClient->Driver(); + + if (CTestBase::iScreenNo == 1) + { + TheClient->iWs.SetFocusScreen(1); + } + else + { + TheClient->iWs.SetFocusScreen(0); + } + + iTestRects.Construct(*BaseWin->Win()); + iStdTestWindowSize=BaseWin->Size(); + iRedrawType=EPartialRedraw_Unknown; // Reset between tests + if (iMaxGrays+iMaxColors==0) + { + TheClient->iWs.GetDefModeMaxNumColors(iMaxColors,iMaxGrays); + iNormalPointerCursorArea=TheClient->iWs.PointerCursorArea(); + } + } + +CTestBase::~CTestBase() + { + delete iMinWin; + delete TheClient; + } + +void CTestBase::CloseAllPanicWindows() + { + TInt idFocus = TheClient->iWs.GetFocusWindowGroup(); + TWsEvent event; + event.SetType(EEventKey); + TKeyEvent *keyEvent = event.Key(); + keyEvent->iCode = EKeyEscape; + keyEvent->iScanCode = EStdKeyEscape; + keyEvent->iModifiers = 0; + TInt theLimit = 50; + while(idFocus != NULL && (theLimit-- > 0)) + { + TheClient->iWs.SendEventToAllWindowGroups(event); + idFocus = TheClient->iWs.GetFocusWindowGroup(); + } + } + +/** +Returns the size of the standard test windows. +@see iStdTestWindowSize +*/ +const TSize& CTestBase::StdTestWindowSize() + { + return iStdTestWindowSize; + } + +/** Returns the number of greys available in the richest grey mode */ +TInt CTestBase::MaxGrays() const + { + return iMaxGrays; + } + +/** Returns the number of colours available in the richest supported colour mode. */ +TInt CTestBase::MaxColors() const + { + return iMaxColors; + } + +void CTestBase::TriggerFail() + { + iFail=ETrue; + } + +void CTestBase::LogLeave(TInt aErr) + { + TLogMessageText buf; + _LIT(Leave,"AUTO Left with error code %d in "); + buf.AppendFormat(Leave,aErr); + buf.Append(iSubTitle); + TheClient->LogMessage(buf); + } + +void CTestBase::LogSubTest(const TDesC &aSubTitle) + { + Driver()->iSubTestNum++; + iSubTitle=aSubTitle; + iTestBase->Logger().Write(TheClient->StdLogWindow().LogSubTest(aSubTitle,iState)); + } + +void CTestBase::LogMessage(TInt aValue) + { + _LIT(WinID,"Win Id:"); + TheClient->StdLogWindow().LogMessage(EFalse,WinID,aValue); + } + +void CTestBase::LogSubState(TInt aSubState) + { + _LIT(SubTest,"SubState"); + iTestBase->Logger().Write(TheClient->StdLogWindow().LogMessage(ETrue,SubTest,aSubState)); + } + +TBool DoCheckRectRWin(RWindowBase &aWin1,RWindowBase &aWin2,const TRect &aRect) + { + TRect rect1(aRect); + TRect rect2(aRect); + rect1.Move(aWin1.InquireOffset(*TheClient->iGroup->WinTreeNode())); + rect2.Move(aWin2.InquireOffset(*TheClient->iGroup->WinTreeNode())); + TBool match=TheClient->iScreen->RectCompare(rect1,rect2); +#if defined(__WINS__) + if (!match) + FindNonMatchingPixel(rect1.iTl,rect2.iTl,aRect.Size()); +#endif + return match; + } + +TBool DoCheckRectRWin(RWindowBase &aWin1,RWindowBase &aWin2,const TRect &aRect, TUint aFlags) + { + TRect rect1(aRect); + TRect rect2(aRect); + rect1.Move(aWin1.InquireOffset(*TheClient->iGroup->WinTreeNode())); + rect2.Move(aWin2.InquireOffset(*TheClient->iGroup->WinTreeNode())); + TBool match=TheClient->iScreen->RectCompare(rect1,rect2, aFlags); +#if defined(__WINS__) + if (!match) + FindNonMatchingPixel(rect1.iTl,rect2.iTl,aRect.Size()); +#endif + return match; + } + +TBool DoCheckRect(CTBaseWin *aWin1,CTBaseWin *aWin2,const TRect &aRect) + { + return DoCheckRectRWin(*aWin1->BaseWin(), *aWin2->BaseWin(), aRect); + } + +TBool DoCheckRect(CTBaseWin *aWin1,CTBaseWin *aWin2) + { + TSize winSize=aWin1->Size(); + TRect rect1(aWin1->BaseWin()->InquireOffset(*TheClient->iGroup->WinTreeNode()),winSize); + TRect rect2(aWin2->BaseWin()->InquireOffset(*TheClient->iGroup->WinTreeNode()),winSize); + return TheClient->iScreen->RectCompare(rect1,rect2); + } + +TBool DoCheckRect(CTBaseWin *aWin1, CTBaseWin *aWin2, const TRect &aRect, TUint aFlags) + { + return DoCheckRectRWin(*aWin1->BaseWin(), *aWin2->BaseWin(), aRect, aFlags); + } + + +/** +Compares the contents of 2 rectangular areas of the screen. + +@param aPos1 The top left corner of the first rectangle. +@param aPos2 The top left corner of the second rectangle. +@param aSize The size of the rectangles +@return ETrue if the 2 areas have the same content, EFalse otherwise. +*/ +TBool DoCheckRect(TPoint aPos1,TPoint aPos2,TSize aSize) + { + return TheClient->iScreen->RectCompare(TRect(aPos1,aSize),TRect(aPos2,aSize)); + } + +void CTestBase::DrawTestBackground(TBool aInvertColors, const TSize &aSize, TInt aGrays/*=16*/) +// +// Draws a standard test background with a mix of colors (shades). +// This is mainly used to test for graphic functions writing outside the intended area. +// +// This code assumes an TheGc is already active on the window to use. +// + { + TheGc->SetBrushColor(TRgb::Gray256(255)); + TInt step=5; + TInt col=0; + TInt colorInc=(aGrays>9 ? 17 : 85); + TheGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + TheGc->SetPenStyle(CGraphicsContext::ENullPen); + for(TInt row=0;rowSetBrushColor(TRgb::Gray256(aInvertColors ? 255-col:col)); + TheGc->DrawRect(TRect(0,row,aSize.iWidth,row+step)); + col=col+colorInc; + if (col>255) + col=0; + } + } + +void CTestBase::AbortL() + { + CTestDriver* driver=iDriver; + iDriver->DestroyTest(); + driver->TestComplete2(); + User::Leave(ETestFailed); + } + +/*CTWsGraphicsBase*/ + +CTWsGraphicsBase::CTWsGraphicsBase(CTestStep* aStep) : CTGraphicsBase(aStep) + { + } + +CTWsGraphicsBase::~CTWsGraphicsBase() + { + delete iTest; + } + +void CTWsGraphicsBase::CreateTestBaseL(CTTMSGraphicsStep* aTmsStep) + { + __ASSERT_ALWAYS(iTest==NULL,AutoPanic(EAutoPanicRecalledCreateTestBaseL)); + iTest=new(ELeave) CTestBase(iStep->TestStepName(),this); + iTmsStep = aTmsStep; + } +/** +Gets the Screen Number from an .ini file supplied to the RUN_TEST_STEP. Screen number should +be put under the section [useScreen] as screen=0 or screen=1. + +@return Screen number Defined in .ini file, otherwise 0. +*/ +TInt CTWsGraphicsBase::GetScreenFromIni() const + { + _LIT(KUseScreenSection, "useScreen"); + _LIT(KScreen, "screen"); + + TInt screen = 0; + TBool configAvailable = iStep->GetIntFromConfig(KUseScreenSection, KScreen, screen); + if(configAvailable) + { + return screen; + } + else + { + return 0; + } + } + +void CTWsGraphicsBase::TestComplete() + { + _LIT(KTestComplete,"Test complete"); + INFO_PRINTF1(KTestComplete); + CTGraphicsBase::TestComplete(); + } + +void CTWsGraphicsBase::LogMessage(const TText8* aFile,TInt aLine,TRefByValue aFmt,...) + { + TLogMessageText buf; + VA_LIST list; + VA_START(list,aFmt); + buf.AppendFormatList(aFmt,list); + TheClient->LogMessage(buf); + Logger().LogExtra(aFile,aLine,ESevrInfo,buf); + VA_END(list); + } + +TBool CTWsGraphicsBase::CheckRetValue(TBool aPass, const TDesC *aErrorMsg, const TDesC &aErrorFunction) + { + if (!aPass && aErrorMsg) + { + LOG_MESSAGE3(_L("%S %S failed"),aErrorMsg,&aErrorFunction); + iTmsStep->MQCTest(EFalse,((TText8*)__FILE__),__LINE__); + } + iStep->TEST(aPass); + return aPass; + } + +void CTWsGraphicsBase::CompareWindowsSoftFailWinscw(const TText8* aFile, TInt aLine) + { + if (!DoCheckRect(BaseWin, TestWin, BaseWin->Size())) + { +#ifdef __WINS__ + _LIT(KMessage,"ERROR: Test Failed but is ignored on WINSCW"); + Logger().LogExtra(aFile, aLine, ESevrErr, KMessage); +#else // __WINS__ + iStep->TEST(EFalse); + _LIT(KMessage,"ERROR: Test Failed"); + Logger().LogExtra(aFile, aLine, ESevrErr, KMessage); +#endif // __WINS__ + } + } + +void CTWsGraphicsBase::CheckRect(TPoint aPos1,TPoint aPos2,TSize aSize, const TDesC *aErrorMsg) + { + CheckRetValue(DoCheckRect(aPos1,aPos2,aSize),aErrorMsg,_L("CheckRect()")); + } + +void CTWsGraphicsBase::CheckRect(TPoint aPos1,TPoint aPos2,TSize aSize, const TDesC &aErrorMsg) + { + CheckRect(aPos1,aPos2,aSize,&aErrorMsg); + } + +void CTWsGraphicsBase::CheckRectNoMatch(TPoint aPos1,TPoint aPos2,TSize aSize, const TDesC *aErrorMsg) + { + CheckRetValue(!DoCheckRect(aPos1,aPos2,aSize),aErrorMsg,_L("CheckRectNoMatch()")); + } + +void CTWsGraphicsBase::CheckRectNoMatch(TPoint aPos1,TPoint aPos2,TSize aSize, const TDesC &aErrorMsg) + { + CheckRectNoMatch(aPos1,aPos2,aSize,&aErrorMsg); + } + +void CTWsGraphicsBase::CheckRect(CTBaseWin *aWin1,CTBaseWin *aWin2, const TDesC *aErrorMsg) + { + CheckRetValue(DoCheckRect(aWin1,aWin2),aErrorMsg,_L("CheckRect()")); + } + +void CTWsGraphicsBase::CheckRect(CTBaseWin *aWin1,CTBaseWin *aWin2, const TDesC &aErrorMsg) + { + CheckRect(aWin1,aWin2,&aErrorMsg); + } + +void CTWsGraphicsBase::CheckRectNoMatch(CTBaseWin *aWin1,CTBaseWin *aWin2, const TDesC *aErrorMsg) + { + CheckRetValue(!DoCheckRect(aWin1,aWin2),aErrorMsg,_L("CheckRectNoMatch()")); + } + +void CTWsGraphicsBase::CheckRectNoMatch(CTBaseWin *aWin1,CTBaseWin *aWin2, const TDesC &aErrorMsg) + { + CheckRectNoMatch(aWin1,aWin2,&aErrorMsg); + } + +TBool CTWsGraphicsBase::CheckRect(CTBaseWin *aWin1,CTBaseWin *aWin2,const TRect &aRect, const TDesC *aErrorMsg) + { + return CheckRetValue(DoCheckRect(aWin1,aWin2,aRect),aErrorMsg,_L("CheckRect()")); + } + +TBool CTWsGraphicsBase::CheckRect(CTBaseWin *aWin1,CTBaseWin *aWin2,const TRect &aRect, const TDesC &aErrorMsg) + { + return CheckRect(aWin1,aWin2,aRect,&aErrorMsg); + } + +void CTWsGraphicsBase::CheckRectNoMatch(CTBaseWin *aWin1,CTBaseWin *aWin2,const TRect &aRect, const TDesC *aErrorMsg) + { + CheckRetValue(!DoCheckRect(aWin1,aWin2,aRect),aErrorMsg,_L("CheckRectNoMatch()")); + } + +void CTWsGraphicsBase::CheckRectNoMatch(CTBaseWin *aWin1,CTBaseWin *aWin2,const TRect &aRect, const TDesC &aErrorMsg) + { + CheckRectNoMatch(aWin1,aWin2,aRect,&aErrorMsg); + } + +void CTWsGraphicsBase::CompareWindows(const TRect &aRect, const TDesC *aErrorMsg) + { + CheckRetValue(DoCheckRect(BaseWin,TestWin,aRect),aErrorMsg,_L("CompareWindows()")); + } + +TBool CTWsGraphicsBase::CompareWindows(const TDesC *aErrorMsg) + { + return CheckRetValue(DoCheckRect(BaseWin,TestWin,TRect(BaseWin->Size())),aErrorMsg,_L("CompareWindows()")); + } + +void CTWsGraphicsBase::CompareWindows(const TRect &aRect, const TDesC &aErrorMsg) + { + CompareWindows(aRect,&aErrorMsg); + } + +TBool CTWsGraphicsBase::CompareWindows(const TDesC &aErrorMsg) + { + return CompareWindows(&aErrorMsg); + } + +/** +Returns the size of the standard test windows. + +Several tests use 3 windows : one is a log window, one is a reference window +and one is the actual output of the test. All these windows have the same width which is roughly +1/3 of the screen. They also have the same height which is roughly equal to the screen height. +*/ +const TSize& CTWsGraphicsBase::StdTestWindowSize() + { + return iTest->StdTestWindowSize(); + } + +/** Returns the number of greys available in the richest grey mode */ +TInt CTWsGraphicsBase::MaxGrays() const + { + return iTest->MaxGrays(); + } + +/** Returns the number of colours available in the richest supported colour mode. */ +TInt CTWsGraphicsBase::MaxColors() const + { + return iTest->MaxColors(); + } + +// +// Panic testing // +// + +LOCAL_C TInt PanicThreadFunc(TAny *aPtr) + { + CTrapCleanup* CleanUpStack=CTrapCleanup::New(); + SPanicParams *ptr=(SPanicParams *)aPtr; + TInt ret; + TRAP(ret,ret=(*ptr->func)(ptr->num,ptr->ptr)); + delete CleanUpStack; + if (ret==EWsExitReasonBad) + AutoPanic(EAutoPanicPanicFailed); + return(ret); + } + +TInt CTestBase::LaunchPanicThread(RThread &aThread, SPanicParams *aPtr) + { + TBuf<32> threadName; + threadName.Format(TRefByValue(_L("AutoPanicThread%d")),iThreadNumber++); + return(aThread.Create(threadName,PanicThreadFunc,KDefaultStackSize,KPanicThreadHeapSize,KPanicThreadHeapSize,aPtr,EOwnerThread)); + } + +TInt CTestBase::TestPanicL(SPanicParams *aPtr, TInt aExitReason, const TDesC &aCategory, TBool* aTestFinished) + { + RThread thread; + TRequestStatus stat; + TInt err=LaunchPanicThread(thread, aPtr); + if (err==KErrAlreadyExists) + { + // wait for kernel to clear up old threads + // and have several attempts at starting the thread + // if unsuccessful the first time + for (TInt i=0;i<3;i++) + { + User::After(TTimeIntervalMicroSeconds32(100000)); //0.1 secs + err=LaunchPanicThread(thread, aPtr); + if (err!=KErrAlreadyExists) + break; + } + } + User::LeaveIfError(err); + thread.Logon(stat); + User::SetJustInTime(EFalse); + thread.Resume(); + User::WaitForRequest(stat); + User::SetJustInTime(ETrue); + + TBool testFinished=EFalse; + TBool testPassed=ETrue; + if (thread.ExitType()==EExitKill) + { + User::LeaveIfError(thread.ExitReason()); + if(thread.ExitReason()!=EWsExitReasonFinished) + { + testPassed=EFalse; + } + testFinished=ETrue; // Finish tests + } + else + { + if ((thread.ExitCategory().Compare(aCategory)!=0) + || (aExitReason!=EWservNoPanic && thread.ExitReason()!=aExitReason) + || (thread.ExitType()!=EExitPanic)) + { + testPassed=EFalse; + } + } + + if(aTestFinished) + *aTestFinished=testFinished; + thread.Close(); + return(testPassed); + } + +TInt CTestBase::TestWsPanicL(TPanicFunction aFunction, TClientPanic aExitReason, TInt aInt, TAny *aPtr, TBool* aTestFinished) + { + return TestPanicL(aFunction,aExitReason,aInt,aPtr,KWSERV, aTestFinished); + } + +TInt CTestBase::TestW32PanicL(TPanicFunction aFunction, TW32Panic aExitReason, TInt aInt, TAny *aPtr, TBool* aTestFinished) + { + return TestPanicL(aFunction,aExitReason,aInt,aPtr,KW32,aTestFinished); + } + + TInt CTestBase::TestWservPanicL(TPanicFunction aFunction, TWservPanic aExitReason, TInt aInt, TAny *aPtr) + { + _LIT(KWSERV1,"Wserv Internal Panic"); + return TestPanicL(aFunction,aExitReason,aInt,aPtr,KWSERV1); + } + +TInt CTestBase::TestPanicL(TPanicFunction aFunction, TInt aExitReason, TInt aInt, TAny *aPtr, const TDesC &aCategory, TBool* aTestFinished) + { + SPanicParams params; + params.num=aInt; + params.func=aFunction; + params.ptr=aPtr; + return TestPanicL(¶ms, aExitReason, aCategory, aTestFinished); + } + +TBool CTestBase::IsFullRomL() + { + TBool isFullRom = EFalse; + _LIT(KWinName,"EikonServer"); + TInt numWinGroups=TheClient->iWs.NumWindowGroups(); + CArrayFixFlat* list=new(ELeave) CArrayFixFlat(numWinGroups); + TheClient->iWs.WindowGroupList(list); + numWinGroups=list->Count(); // Just in case it changed between originally getting it and getting the actual list + TBuf<64> name; + TInt ii; + for(ii=0;iiiWs.GetWindowGroupNameFromIdentifier((*list)[ii],name); + #ifndef DISABLE_FAIL_DIALOG + TInt ordinalPos=0; + ordinalPos+=ordinalPos; //To stop a warning + ordinalPos= + #endif + TheClient->iWs.GetWindowGroupOrdinalPriority((*list)[ii]); + if (name==KWinName) + { + isFullRom = ETrue; + break; + } + } + delete list; + return isFullRom; + } + +void CTestBase::DelayIfFullRomL() + { + if (IsFullRomL()) + User::After(400000); + } + +TPartialRedrawType CTestBase::RedrawStoreTypeL() + { +/* if (iRedrawType==EPartialRedraw_Unknown) + { + const TRgb KRed=TRgb(255,0,0); + const TRgb KGreen=TRgb(0,255,0); + const TRgb KBlue=TRgb(0,0,255); + CWsScreenDevice* scrDev=TheClient->iScreen; + TSize winSize=scrDev->SizeInPixels(); + CBlankWindow* win=new(ELeave) CBlankWindow(KRed); //Window will be red if WSERV just draws in background color + CleanupStack::PushL(win); + TDisplayMode mode=EColor256; + win->SetUpL(TPoint(),winSize,TheClient->iGroup,*TheClient->iGc,&mode); //Window is activated + win->RealDraw(ETrue); + win->SetColor(KGreen); + CBlankWindow* win2=new(ELeave) CBlankWindow(KRed); + CleanupStack::PushL(win2); + win2->SetUpL(TPoint(),winSize,TheClient->iGroup,*TheClient->iGc,&mode); //New Window completely obscures other window + win2->RealDraw(ETrue); + win->CTWin::DrawNow(); //Window will be green if drawn from stored commands + win2->CTWin::DrawNow(); + win2->SetVisible(EFalse); + TRgb col; + scrDev->GetPixel(col,TPoint(5,5)); //Pixel will be red if storing off by default and green otherwise + if (col==KRed) + { + win->Win()->EnableRedrawStore(ETrue); + win->CTWin::DrawNow(); //Create stored commands + } + else + __ASSERT_ALWAYS(col==KGreen,AutoPanic(EAutoPanicRedrawStoring)); + win->SetColor(KBlue); + TRect redrawRect(TSize(10,10)); + win->Invalidate(redrawRect); + win->Win()->BeginRedraw(redrawRect); + win->DrawNow(redrawRect); //Top left of Window will be blue if it draws itself + win->Win()->EndRedraw(); + win2->SetVisible(ETrue); + win2->SetVisible(EFalse); + scrDev->GetPixel(col,TPoint(5,5)); //Pixel will be red if stored commands were lost + iRedrawType=EPartialRedraw_None; + if (col!=KRed) + { + __ASSERT_ALWAYS(col==KBlue,AutoPanic(EAutoPanicRedrawStoring)); + TheClient->WaitForRedrawsToFinish(); + win2->SetVisible(ETrue); + win2->SetVisible(EFalse); + scrDev->GetPixel(col,TPoint(15,15)); //Pixel will be blue if partial redraw triggers full redraw + iRedrawType=EPartialRedraw_PreserveStoredCmds; + if (col!=KBlue) + { + __ASSERT_ALWAYS(col==KGreen,AutoPanic(EAutoPanicRedrawStoring)); + iRedrawType=EPartialRedraw_FullRedrawSupport; + } + } + CleanupStack::PopAndDestroy(2,win); + } + return iRedrawType;*/ + return EPartialRedraw_FullRedrawSupport; + } + +void CTestBase::SetUpMember(TSpriteMember &aMember) + { + aMember.iMaskBitmap=NULL; + aMember.iInvertMask=EFalse; + aMember.iDrawMode=CGraphicsContext::EDrawModePEN; + aMember.iOffset=TPoint(); + aMember.iInterval=TTimeIntervalMicroSeconds32(0); + } + +void CTestBase::SimulateKeyDownUpWithModifiers(TInt aScanCode,TUint aModifiers) + { + if (aModifiers&EModifierAlt) + SimulateKey(TRawEvent::EKeyDown,EStdKeyLeftFunc); + if (aModifiers&EModifierCtrl) + SimulateKey(TRawEvent::EKeyDown,EStdKeyLeftCtrl); + if (aModifiers&EModifierShift) + SimulateKey(TRawEvent::EKeyDown,EStdKeyLeftShift); + SimulateKeyDownUp(aScanCode); + if (aModifiers&EModifierShift) + SimulateKey(TRawEvent::EKeyUp,EStdKeyLeftShift); + if (aModifiers&EModifierCtrl) + SimulateKey(TRawEvent::EKeyUp,EStdKeyLeftCtrl); + if (aModifiers&EModifierAlt) + SimulateKey(TRawEvent::EKeyUp,EStdKeyLeftFunc); + } + +void CTestBase::SimulateKeyDownUp(TInt aScanCode) + { + __ASSERT_DEBUG(aScanCode<'a' || aScanCode>'z',AutoPanic(EAutoPanicScanCapital)); + SimulateKey(TRawEvent::EKeyDown,aScanCode); + SimulateKey(TRawEvent::EKeyUp,aScanCode); + } + +void CTestBase::SimulatePointerDownUp(TInt aX, TInt aY) + { + SimulatePointer(TRawEvent::EButton1Down,aX,aY); + SimulatePointer(TRawEvent::EButton1Up,aX,aY); + } + +void CTestBase::SimulateKey(TRawEvent::TType aType, TInt aScanCode) + { + TRawEvent rawEvent; + rawEvent.Set(aType,aScanCode); + TheClient->iWs.SimulateRawEvent(rawEvent); + } + +/** + * Determine if the configuration supports pointer event testing. + * + * There are certain circumstances where we want to skip pointer event + * testing because we are simulating pointer events, and don't want to + * simulate a pointer event from an impossible co-ordinate. We'd rather + * just identify that there is no point in doing the test and skip over + * to the next test case. + * + * In particular, when a ROM configured with a digitiser is deployed on a + * Naviengine, with hardware configuration DIP switches which say that there + * is an external screen connected, then no touch pad is active. + * The base port under these conditions returns a digitiser area (0,0,0,0) + * + * @return ETrue if the configuration supports pointer event testing, otherwise + * return EFalse. + */ +TBool CTestBase::ConfigurationSupportsPointerEventTesting() const + { + if (iNormalPointerCursorArea.IsEmpty()) + { + return EFalse; + } + return ETrue; + } + + +void CTestBase::SimulatePointer(TRawEvent::TType aType, TInt aX, TInt aY) + { + __ASSERT_DEBUG(ConfigurationSupportsPointerEventTesting(), AutoPanic(EAutoPanicNoDigitiser)); + + +#ifdef WSERV_TAUTO_LOG_POINTER_EVENTS + TLogMessageText buf; + _LIT(KLog,"SimulatePointer Type=%d Pos=(%d,%d)"); + buf.Format(KLog,aType,aX,aY); + TheClient->LogMessage(buf); +#endif + + TRawEvent rawEvent; + rawEvent.Set(aType,aX,aY); + TheClient->iWs.SimulateRawEvent(rawEvent); + } + +void CTestBase::SimulateEvent(TRawEvent::TType aType) + { + TRawEvent rawEvent; + rawEvent.Set(aType); + TheClient->iWs.SimulateRawEvent(rawEvent); + } + +void CTestBase::LogColors(const CBitmapDevice& aDevice,TPoint aBasePoint, TPoint aStartPoint, TPoint aEndPoint) + { + _LIT(KPixel,"Pixel(%d,%d) R=%d G=%d B=%d"); + TLogMessageText buf; + TBuf8<2560> screen; + const TRgb* pixel; + if (aStartPoint.iX==aEndPoint.iX) + ++aEndPoint.iX; + if (aStartPoint.iY==aEndPoint.iY) + ++aEndPoint.iY; + TInt width=aEndPoint.iX-aStartPoint.iX; + TInt xx,yy; + for (yy=aStartPoint.iY;yyRed(),pixel->Green(),pixel->Blue()); + //RDebug::Print(buf); + TheClient->iWs.LogMessage(buf); + } + } + TheClient->iWs.Flush(); + } + +void CTestBase::LogColors4(const CBitmapDevice& aDevice,TPoint aStartPoint,TInt aLen) + { + _LIT(KValue,"Pixel(%d,%d) Byte %d, Value %d"); + TLogMessageText buf; + TBuf8<2560> screen; + aDevice.GetScanLine(screen,aStartPoint,aLen,EGray4); + TInt len=(aLen+3)/4; + TInt ii; + for (ii=0;iiiWs.LogMessage(buf); + } + } + +void CTestBase::UpdateTestResults(TInt aNoOfTest, TInt aNoOfTestPass) + { + iNumberTests+=aNoOfTest; + iNumberTestsPass+=aNoOfTestPass; + } + +TInt CTestBase::SaveScreen(const TDesC& aFileName) + { + return SaveScreen(aFileName,TheClient->iScreen->SizeInPixels(),TheClient->iScreen->DisplayMode()); + } + +TInt CTestBase::SaveScreen(const TDesC& aFileName,const TSize& aScreenSize,TDisplayMode aColorDepth) + { + TRAPD(err,SaveScreenL(aFileName,aScreenSize,aColorDepth)); + return err; + } + +void CTestBase::SaveScreenL(const TDesC& aFileName,const TSize& aScreenSize,TDisplayMode aColorDepth) + { + CBitmap* copyOfScreen=CBitmap::NewLC(aScreenSize,aColorDepth); + CFbsScreenDevice* scrDevice=CFbsScreenDevice::NewL(iScreenNumber,aColorDepth); + CleanupStack::PushL(scrDevice); + CFbsBitGc* gc; + User::LeaveIfError(scrDevice->CreateContext(gc)); + CleanupStack::PushL(gc); + copyOfScreen->Gc().BitBlt(TPoint(),*gc); + User::LeaveIfError(copyOfScreen->Bitmap().Save(aFileName)); + CleanupStack::PopAndDestroy(3,copyOfScreen); + } + + +/*CProcess*/ +_LIT(KScreenTag,"Screen"); + +void CProcess::GetProcArg(const TWinCommand& aParam,TBufArg& aProcArg) + { + TInt pos = aParam.Find(KScreenTag); + if (pos!=KErrNotFound) + aProcArg = aParam.Left(pos-1); + else + aProcArg = aParam; + } + +void CProcess::GetScreenArg(const TWinCommand& aParam, TInt& aScreenArg) + { + TInt pos = aParam.Find(KScreenTag); + if (pos!=KErrNotFound) + { + TBufArg secondArg(aParam.Right(aParam.Length()-pos)); + if (secondArg.Length()>6) + { + TBuf<1> digit(secondArg.Mid(6,1)); + TLex lex(digit); + lex.Val(aScreenArg); + } + } + } + +TInt CProcess::Start(const TWinCommand& aParam) + { + // parse command line aParam to retrieve value of + // screen number if it is specified + // + // command line format: [screen] + // + TBufArg procArg(_L("")); + TInt screenArg = KDefaultScreen; + + GetProcArg(aParam, procArg); + GetScreenArg(aParam, screenArg); + + TInt ii; + for(ii=0;iiConstructL(aFunctionNo,aScreenNumber); + CleanupStack::Pop(self); + return self; + } + +CProcess* CProcess::NewTL(TInt aFunctionNo,TInt aScreenNumber,TRequestStatus* aStatus /*=NULL*/) + { + CProcess* self=new(ELeave) CProcess(); + CleanupStack::PushL(self); + self->ConstructTL(aFunctionNo,aScreenNumber,aStatus); + CleanupStack::Pop(self); + return self; + } + +CProcess* CProcess::NewThreadL(const TDesC& aName,TThreadFunction aFunction,TThreadStartUp* aPtr + ,TRequestStatus* aStatus) + { + CProcess* self=new(ELeave) CProcess(); + CleanupStack::PushL(self); + self->ConstructL(aName,aFunction,aPtr,aStatus); + CleanupStack::Pop(self); + return self; + } + +CProcess* CProcess::NewThreadRendezvousL(const TDesC& aName,TThreadFunction aFunction,TThreadStartUp* aPtr ,TRequestStatus* aLogonStatus,TRequestStatus& aRendesvouzStatus) + { + CProcess* self=new(ELeave) CProcess(); + CleanupStack::PushL(self); + self->ConstructRendezvousL(aName,aFunction,aPtr,aLogonStatus,aRendesvouzStatus); + CleanupStack::Pop(self); + return self; + } + +CProcess* CProcess::NewThreadRendezvousL(const TDesC& aName,TThreadStartUp* aPtr,TRequestStatus& aRendesvouzStatus) + { + return NewThreadRendezvousL(aName,ThreadInit,aPtr,NULL,aRendesvouzStatus); + } + +CProcess* CProcess::NewThreadL(const TDesC& aName,TThreadStartUp* aPtr) + { + return NewThreadL(aName,ThreadInit,aPtr,NULL); + } + +CProcess* CProcess::NewSimpleThreadL(const TDesC& aName,TThreadStartUp* aPtr,TRequestStatus* aStatus/*=NULL*/) + { + return NewThreadL(aName,SimpleThreadInit,aPtr,aStatus); + } + +_LIT(KSpace," "); +_LIT(KScreenFormat,"%d"); + +void CProcess::ConstructL(TInt aFunctionNo,TInt aScreenNumber/*=KDefaultScreen*/) + { + Close(); + // add screen number into command line param + // format: [screen] + // + TBuf<100> commandLine; + + commandLine = iFunctions[aFunctionNo].iParam; + commandLine.Append(KSpace); + commandLine.Append(KScreenTag); + commandLine.AppendFormat(KScreenFormat,aScreenNumber); + User::LeaveIfError(iOther.Create(RProcess().FileName(),commandLine)); + iCreated|=eOtherCreated; + iOther.Resume(); + } + +void CProcess::ConstructTL(TInt aFunctionNo,TInt aScreenNumber/*=KDefaultScreen*/,TRequestStatus* aStatus) + { + Close(); + TUint flag=eThreadCreated; + TInt err=iThread.Create(iFunctions[aFunctionNo].iParam,iFunctions[aFunctionNo].iFunction + ,KDefaultStackSize,KOtherProcHeapSize,KOtherProcHeapSize,(TAny*)aScreenNumber,EOwnerThread); + User::LeaveIfError(err); + iCreated|=flag; + if (aStatus) + Logon(*aStatus); + iThread.Resume(); + } + + +void CProcess::ConstructL(const TDesC& aName,TThreadFunction aFunction,TThreadStartUp* aPtr,TRequestStatus* aStatus) + { + Close(); + User::LeaveIfError(iThread.Create(aName,aFunction,KDefaultStackSize,KOtherProcHeapSize,KOtherProcHeapSize,aPtr,EOwnerThread)); + iCreated|=eThreadCreated; + if (aStatus) + Logon(*aStatus); + iThread.Resume(); + } + +void CProcess::ConstructRendezvousL(const TDesC& aName,TThreadFunction aFunction,TThreadStartUp* aPtr,TRequestStatus* aLogonStatus,TRequestStatus& aRendezvousStatus) + { + Close(); + User::LeaveIfError(iThread.Create(aName,aFunction,KDefaultStackSize,KOtherProcHeapSize,KOtherProcHeapSize,aPtr,EOwnerThread)); + iCreated|=eThreadCreated; + if (aLogonStatus) + Logon(*aLogonStatus); + + iThread.Rendezvous(aRendezvousStatus); + iThread.Resume(); + } + +void CProcess::Logon(TRequestStatus& aStatus) const + { + if (iCreated&eThreadCreated) + iThread.Logon(aStatus); + else + { + iOther.Logon(aStatus); + } + } + +void CProcess::Terminate(TInt aReason) + { + if (iCreated&eThreadCreated) + iThread.Terminate(aReason); + else + { + iOther.Terminate(aReason); + } + Close(); + } + +void CProcess::Close() + { + if (iCreated&eOtherCreated) + iOther.Close(); + if (iCreated&eThreadCreated) + iThread.Close(); + iCreated=0; + } + +CProcess::~CProcess() + { + Close(); + } + +TBool CProcess::StillAlive() + { + if (iCreated&eOtherCreated) + return iOther.ExitType()==EExitPending; + return iThread.ExitType()==EExitPending; + } + +void CProcess::LeaveIfDied() //Can Leave + { + User::After(200000); //0.2 secs + if (StillAlive()) + return; + if (iCreated&eOtherCreated) + User::Leave(iOther.ExitReason()); + User::Leave(iThread.ExitReason()); + } + +const TInt KFirstInstanceId = 1; +const TInt KOtherInstanceId = 2; + +TBool CProcess::ProcessDied(TInt aScreenNo/*=KDefaultScreen*/) + { + _LIT(pName,"TAutoServer*"); + TFindProcess find(pName); + TFullName name; + + TBool found = EFalse; + TInt instanceId = aScreenNo==KDefaultScreen? KFirstInstanceId : KOtherInstanceId; + // find the correct instance of the process + // required in multi display test + while (!found && find.Next(name)==KErrNone) + { + TPtrC scrId = name.Right(1); + TInt id; + TLex lex(scrId); + lex.Val(id); + if (id==instanceId) + found = ETrue; + } + if (!found) + return EFalse; + + RProcess p; + p.Open(name); + if (p.Id()!=RProcess().Id()) + return EFalse; + p.Close(); + return (find.Next(name)!=KErrNone); + } + +TInt CProcess::ThreadInit(TAny *aPtr) + { + __UHEAP_MARK; + TInt err=KErrNone; + CTrapCleanup* CleanUpStack=CTrapCleanup::New(); + if (CleanUpStack==NULL) + err=KErrNoMemory; + else + { + TRAP(err,InitialiseL(STATIC_CAST(TThreadStartUp*,aPtr))) + delete CleanUpStack; + } + __UHEAP_MARKEND; + return(err); + } + +void CProcess::InitialiseL(TThreadStartUp* aPtr) + { + CActiveScheduler* activeScheduler=new(ELeave) CActiveScheduler; + CActiveScheduler::Install(activeScheduler); + CleanupStack::PushL(activeScheduler); + aPtr->iInitFunction(aPtr->iParam); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(activeScheduler); + } + +TInt CProcess::SimpleThreadInit(TAny *aPtr) + { + __UHEAP_MARK; + TInt err=KErrNone; + CTrapCleanup* CleanUpStack=CTrapCleanup::New(); + if (CleanUpStack==NULL) + err=KErrNoMemory; + else + { + TThreadStartUp* ptr=STATIC_CAST(TThreadStartUp*,aPtr); + ptr->iInitFunction(ptr->iParam); + delete CleanUpStack; + } + __UHEAP_MARKEND; + return(err); + } + +/*CMinWin*/ + +CMinWin::CMinWin(TInt aScreenNo): iScreenNo(aScreenNo) + {} + +void CMinWin::ConstructL() + { + User::LeaveIfError(iWs.Connect()); + iScr=new(ELeave) CWsScreenDevice(iWs); + User::LeaveIfError(iScr->Construct(iScreenNo)); + iGroup=RWindowGroup(iWs); + User::LeaveIfError(iGroup.Construct(8970+iScreenNo,ETrue)); + iWin=RWindow(iWs); + User::LeaveIfError(iWin.Construct((RWindowTreeNode)iGroup,(TUint32)this)); + iRect=TSize(10,10); + iWin.SetExtent(TPoint(0,0),iRect.Size()); + iWin.SetRequiredDisplayMode(EColor256); + iWin.SetBackgroundColor(KRgbGreen); + iWin.Activate(); + iGc=new(ELeave) CWindowGc(iScr); + User::LeaveIfError(iGc->Construct()); + + Draw(iRect); + iWs.Flush(); + } + +CMinWin::~CMinWin() + { + delete iGc; + iWin.Close(); + iGroup.Close(); + delete iScr; + iWs.Close(); + } + +void CMinWin::Draw(const TRect& aRect) + { + iWin.BeginRedraw(); + iGc->Activate(iWin); + iGc->SetPenStyle(CGraphicsContext::ENullPen); + iGc->SetBrushStyle(CGraphicsContext::ESolidBrush); + iGc->SetBrushColor(KRgbGreen); + iGc->DrawRect(aRect); + iGc->Deactivate(); + iWin.EndRedraw(); + } + + +/*CTimeOut*/ + +void CTimeOut::ConstructL() + { + CTimer::ConstructL(); + CActiveScheduler::Add(this); + } + +void CTimeOut::Start(TTimeIntervalMicroSeconds32 aInterval,TCallBack aCallBack) + { + iCallBack=aCallBack; + After(aInterval); + } + +void CTimeOut::RunL() + { + iCallBack.CallBack(); + } + +/* + * Simply returns the DisplayMode as a string. Used to display mode details on test results. + */ +GLDEF_C TPtrC DisplayModeAsString(TDisplayMode aMode) + { + + TPtrC modeAsString; + + switch(aMode) + { + case ENone: + _LIT(KENoneMode,"ENone"); + modeAsString.Set(KENoneMode); + break; + case EGray2: + _LIT(KEGray2Mode,"EGray2"); + modeAsString.Set(KEGray2Mode); + break; + case EGray4: + _LIT(KEGray4Mode,"EGray4"); + modeAsString.Set(KEGray4Mode); + break; + case EGray16: + _LIT(KEGray16Mode,"EGray16"); + modeAsString.Set(KEGray16Mode); + break; + case EGray256: + _LIT(KEGray256Mode,"EGray256"); + modeAsString.Set(KEGray256Mode); + break; + case EColor16: + _LIT(KEColor16Mode,"EColor16"); + modeAsString.Set(KEColor16Mode); + break; + case EColor256: + _LIT(KEColor256Mode,"EColor256"); + modeAsString.Set(KEColor256Mode); + break; + case EColor64K: + _LIT(KEColor64KMode,"EColor64K"); + modeAsString.Set(KEColor64KMode); + break; + case EColor16M: + _LIT(KEColor16MMode,"EColor16M"); + modeAsString.Set(KEColor16MMode); + break; + case EColor4K: + _LIT(KEColor4KMode,"EColor4K"); + modeAsString.Set(KEColor4KMode); + break; + case EColor16MU: + _LIT(KEColor16MUMode,"EColor16MU"); + modeAsString.Set(KEColor16MUMode); + break; + case EColor16MA: + _LIT(KEColor16MAMode,"EColor16MA"); + modeAsString.Set(KEColor16MAMode); + break; + case EColor16MAP: + _LIT(KEColor16MAPMode,"EColor16MAP"); + modeAsString.Set(KEColor16MAPMode); + break; + default: + _LIT(KUnknownMode,"Unknown"); + modeAsString.Set(KUnknownMode); + break; + } + + return modeAsString; + } + +// Check if an area of a bitmap is of a certain color +GLDEF_C TBool LossyCheckBlankBitmap(const CFbsBitmap& aBitmap, const TRect aArea, const TRgb aCheckColor, TBool aLossyCompare) + { + const TReal errorLimit = (aLossyCompare ? 0.05 : 0.00); //Lossy(default) or exact compare? + + TBool result = ETrue; + /* TInt mismatchedPixels = 0; */ // -- Useful for debugging + TRgb bitmapPix = TRgb(0,0,0,0); //testWin Pixel + for (TInt x = 0; x < aArea.Size().iWidth; x++) + { + for (TInt y = 0; y < aArea.Size().iHeight; y++) + { + aBitmap.GetPixel(bitmapPix, TPoint(x,y)); + + //Check if there are differeces in color between the bitmap and the test color + if(((TReal)abs(bitmapPix.Red() - aCheckColor.Red())/255) > errorLimit || + ((TReal)abs(bitmapPix.Blue() - aCheckColor.Blue())/255) > errorLimit || + ((TReal)abs(bitmapPix.Green() - aCheckColor.Green())/255) > errorLimit || + ((TReal)abs(bitmapPix.Alpha() - aCheckColor.Alpha())/255) > errorLimit) + { + /* mismatchedPixels++; */ // -- Useful for debugging + result = EFalse; + break; + } + } + } + + /* INFO_PRINTF2(_L("Number of different pixels: %i"), mismatchedPixels); */ // -- Useful for debugging + return result; + } + +// Compare a section of two bitmaps +GLDEF_C TBool LossyCompareBitmap(const CFbsBitmap& aBitmap1, const CFbsBitmap& aBitmap2, const TRect aCompareRect, TBool aLossyCompare) + { + const TReal errorLimit = (aLossyCompare ? 0.05 : 0.00); //Lossy or Exact compare? + + TBool result = ETrue; + + if (aBitmap1.DisplayMode() != aBitmap2.DisplayMode()) + { + RDebug::Printf(" DisplayMode difference %d, %d", aBitmap1.DisplayMode(), aBitmap2.DisplayMode()); + } + + TRgb bitmap1Pix = TRgb(0,0,0,0); + TRgb bitmap2Pix = TRgb(0,0,0,0); + for (TInt x = 0; x < aCompareRect.Size().iWidth; x++) + { + for (TInt y = 0; y < aCompareRect.Size().iHeight; y++) + { + aBitmap1.GetPixel(bitmap1Pix, TPoint(x,y)); + aBitmap2.GetPixel(bitmap2Pix, TPoint(x,y)); + + //Check if there are differences between the colors of the two bitmaps + if(((TReal)abs(bitmap1Pix.Red() - bitmap2Pix.Red())/255) > errorLimit || + ((TReal)abs(bitmap1Pix.Blue() - bitmap2Pix.Blue())/255) > errorLimit || + ((TReal)abs(bitmap1Pix.Green() - bitmap2Pix.Green())/255) > errorLimit || + ((TReal)abs(bitmap1Pix.Alpha() - bitmap2Pix.Alpha())/255) > errorLimit) + { + /* + * There was a difference so return without checking the rest of the + * bitmap. If you are seeing Lossy compare errors, and want to diagnose + * further, consider switching over to using a recording version of this + * function, LossyCompareBitmapRecord() + */ + result = EFalse; + break; + } + } + } + + return result; + } + +/** + * Compare two bitmaps, optionally a lossy comparison, recording any differences and saving bitmaps + * + * @param aBitmap1 Bitmap being checked + * @param aBitmap2 Reference Bitmap + * @param aCompareRect Area of bitmap to compare + * @param aLossyCompare ETrue means use a lossy compare strategy, else do an exact compare + * @param aPixelsDifferent Returned value representing the number of pixels which are different + * @param aLogger Facility for logging to be reported by this function + * @return ETrue if the bitmaps are the same (or similar). + * Otherwise EFalse, with logging reporting the differences, and bitmaps saved in c:\logs\ + * @pre c:\logs directory must exist + */ +GLDEF_C TBool LossyCompareBitmapRecord(CFbsBitmap& aBitmap1, CFbsBitmap& aBitmap2, const TRect aCompareRect, TBool aLossyCompare, TInt& aPixelsDifferent, CTestExecuteLogger& aLogger) + { + const TReal errorLimit = (aLossyCompare ? 0.05 : 0.00); //Lossy or Exact compare? + + TBool result = ETrue; + TInt mismatchedPixels = 0; + TRgb bitmap1Pix = TRgb(0,0,0,0); + TRgb bitmap2Pix = TRgb(0,0,0,0); + if (aBitmap1.DisplayMode() != aBitmap2.DisplayMode()) + { + aLogger.LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, + _L(" DisplayMode difference %d, %d"), aBitmap1.DisplayMode(), aBitmap2.DisplayMode()); + } + for (TInt x = 0; x < aCompareRect.Size().iWidth; x++) + { + for (TInt y = 0; y < aCompareRect.Size().iHeight; y++) + { + aBitmap1.GetPixel(bitmap1Pix, TPoint(x,y)); + aBitmap2.GetPixel(bitmap2Pix, TPoint(x,y)); + + //Check if there are differences between the colors of the two bitmaps + if(((TReal)abs(bitmap1Pix.Red() - bitmap2Pix.Red())/255) > errorLimit || + ((TReal)abs(bitmap1Pix.Blue() - bitmap2Pix.Blue())/255) > errorLimit || + ((TReal)abs(bitmap1Pix.Green() - bitmap2Pix.Green())/255) > errorLimit || + ((TReal)abs(bitmap1Pix.Alpha() - bitmap2Pix.Alpha())/255) > errorLimit) + { + mismatchedPixels++; + + aLogger.LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, + _L(" Pixel difference %d,%d: %d"),x,y, bitmap1Pix.Difference(bitmap2Pix)); + result = EFalse; + // we loop around again to pick up all the differences + } + } + } + aPixelsDifferent = mismatchedPixels; + + /* + * When the bitmaps are different, we store them locally in c:\\logs in + * timestamped files. Save() is a non-const method; this is why aBitmap1 + * and aBitmap2 are non-const. Saving can fail, perhaps because we have + * exceeded storage limits. + */ + if (!result) + { + TTime now; + now.UniversalTime(); + TInt timestamp = I64INT(now.Int64() & 0x7fffffffu); + timestamp/=1000; // a millisecond resolution is easier to track + TFileName mbmFileSrc; + mbmFileSrc.Format (_L("c:\\logs\\%d_LossyCompareBitmap1.mbm"), timestamp); + TFileName mbmFileDst; + mbmFileDst.Format (_L("c:\\logs\\%d_LossyCompareBitmap2.mbm"), timestamp); + TInt saveResult1; + TInt saveResult2; + saveResult1 = aBitmap1.Save(mbmFileSrc); + saveResult2 = aBitmap2.Save(mbmFileDst); + if (saveResult1 == KErrNone && saveResult2 == KErrNone) + { + aLogger.LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, + _L(" Bitmaps are different: see %S, %S"), &mbmFileSrc, &mbmFileDst); + } + else + { + aLogger.LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, + _L(" Bitmaps are different, but could not save files into c:\\logs : %d %d"), saveResult1, saveResult2); + } + } + + return result; + } + +// Check if an area of a screen is of a certain color +GLDEF_C TBool LossyCheckBlankWindow(const CWsScreenDevice& aScreen, CFbsBitmap& aBitmap, const TRect aArea, const TRgb aCheckColor) + { + aScreen.CopyScreenToBitmap(&aBitmap, aArea); + return LossyCheckBlankBitmap(aBitmap, aArea, aCheckColor); + } + +// Compare a section of two windows on the screen +GLDEF_C TBool LossyCompareWindow(const CWsScreenDevice& aScreen, CFbsBitmap& aBitmap1, CFbsBitmap& aBitmap2, const TRect aCompareRect) + { + aScreen.CopyScreenToBitmap(&aBitmap1, aCompareRect); + aScreen.CopyScreenToBitmap(&aBitmap2, aCompareRect); + return LossyCompareBitmap(aBitmap1, aBitmap2, aCompareRect); + } +