// Copyright (c) 1996-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:
// Test various cases of Wserv panicing client apps
//
//
/**
@file
@test
@internalComponent - Internal Symbian test code
*/
#include "TPANIC.H"
#include "../tlib/testbase.h"
#include <w32debug.h>
#define TEST_BITMAP _L("Z:\\WSTEST\\WSAUTOTEST.MBM")
class RWsSessionHacker : public RWsSession
{
public:
inline RWsBuffer *WsBuffer() const {return(iBuffer);};
inline TInt PanicItSendReceive(TInt aFunction,const TIpcArgs& aArgs) const {return SendReceive(aFunction,aArgs);};
inline TInt PanicItSend(TInt aFunction,const TIpcArgs& aArgs) const {return Send(aFunction,aArgs);};
inline TInt PanicItSendReceive(TInt aFunction) const {return SendReceive(aFunction);};
inline TInt PanicItSend(TInt aFunction) const {return Send(aFunction);};
};
class RWsBufferHacker // copy of original data structure to access buffer data
{
public:
RWsSession* iSession;
CWsGraphic::CManager* iManager;
TBool iAutoFlush;
TPtr8 iBuf;
RWsBuffer* iNext;
TInt iPreviousHandle;
TInt iBufSize;
TInt iMaxBufSize;
TInt iDirectAcessCount;
RArray<TInt> iBitmapArray;
TBool iInvalidBitmapArray;
};
CTPanic::CTPanic(CTestStep* aStep):
CTWsGraphicsBase(aStep)
{
}
CTPanic::~CTPanic()
{
}
LOCAL_C TInt DoDeletedParentTest(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// point to correct screen
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(888));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
switch(aInt)
{
case 1:
RWindow win1(ws);
User::LeaveIfError(win1.Construct(group,1));
RWindow win2(ws);
User::LeaveIfError(win2.Construct(win1,2));
win1.Close();
win2.SetExtent(TPoint(1,2),TSize(3,4));
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
LOCAL_C void ReuseWindow(RWsSession& aWs,RWindowGroup& aGroup,RWindow aCopyWin,RWindow* aPtrWin)
{
aPtrWin->Close();
RWindow win(aWs);
User::LeaveIfError(win.Construct(aGroup,17));
aCopyWin.SetExtent(TPoint(1,2),TSize(3,4));
}
LOCAL_C void ReuseGroupWindow(RWsSession& aWs,RWindowGroup aCopyWin,RWindowGroup* aPtrWin)
{
aPtrWin->Close();
RWindowGroup group(aWs);
User::LeaveIfError(group.Construct(889));
group.EnableReceiptOfFocus(EFalse);
aCopyWin.EnableReceiptOfFocus(EFalse);
}
LOCAL_C void ReuseSprite(RWsSession& aWs,RWindow& aWin,RWsSprite aCopySprite,RWsSprite* aPtrSprite)
{
aPtrSprite->Close();
RWsSprite sprite(aWs);
sprite.Construct(aWin,TPoint(0,0),0);
aCopySprite.SetPosition(TPoint(22,22));
}
LOCAL_C void ReusePointerCursor(RWsSession& aWs,RWsPointerCursor aCopyCursor,RWsPointerCursor* aPtrCursor)
{
aPtrCursor->Close();
RWsPointerCursor cursor(aWs);
cursor.Construct(0);
aCopyCursor.Activate();
}
LOCAL_C TInt DoHandleReUse(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
CWsScreenDevice *scrdev=new(ELeave) CWsScreenDevice(ws);
scrdev->Construct((TInt)aScreenNumber);
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(888));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
RWindow win(ws);
User::LeaveIfError(win.Construct(group,1));
switch(aInt)
{
case 2: //WS_HANDLE_WINDOW
ReuseWindow(ws,group,win,&win);
break;
case 3: //WS_HANDLE_GROUP_WINDOW
ReuseGroupWindow(ws,group,&group);
break;
case 4: //WS_HANDLE_SPRITE
{
RWsSprite sprite(ws);
sprite.Construct(win,TPoint(0,0),0);
ReuseSprite(ws,win,sprite,&sprite);
}
break;
case 5: //WS_HANDLE_POINTER_CURSOR
{
RWsPointerCursor cursor(ws);
cursor.Construct(0);
ReusePointerCursor(ws,cursor,&cursor);
}
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
LOCAL_C TInt DoScreenDevicePanicTest(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
CWsScreenDevice *scrdev=new(ELeave) CWsScreenDevice(ws);
User::LeaveIfError(scrdev->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(888));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
RWindow win(ws);
User::LeaveIfError(win.Construct(group, 1));
win.Activate();
CFbsBitmap *bitmap=new(ELeave) CFbsBitmap;
switch(aInt)
{
case 1:
scrdev->CopyScreenToBitmap(bitmap);
break;
case 2:
scrdev->CopyScreenToBitmap(bitmap,TRect(0,0,10,10));
break;
default:
return(EWsExitReasonFinished);
}
ws.Flush();
return(EWsExitReasonBad);
}
LOCAL_C TInt DoOpcodeTests(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
CWsScreenDevice *scrdev=new(ELeave) CWsScreenDevice(ws);
User::LeaveIfError(scrdev->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(888));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
RWindow win(ws);
User::LeaveIfError(win.Construct(group, 1));
win.Activate();
CWindowGc *gc;
scrdev->CreateContext(gc);
switch(aInt)
{
case 1:
ws.TestWrite(ws.WsHandle(),9999,NULL,0);
break;
case 2:
gc->Activate(win);
win.BeginRedraw();
ws.TestWrite(gc->WsHandle(),9999,NULL,0);
/* This only panics if the command is processed immediately. If it goes into the redraw
store then it will be unable to panic the client untill an additional buffer has been received,
hence the double flush.
*/
win.EndRedraw();
ws.Finish();
win.BeginRedraw();
win.EndRedraw();
break;
case 3:
ws.TestWrite(scrdev->WsHandle(),9999,NULL,0);
break;
case 4:
{
CWsBitmap *bitmap=new(ELeave) CWsBitmap(ws);
bitmap->Create(TSize(10,10),EGray4);
ws.TestWrite(bitmap->WsHandle(),9999,NULL,0);
}
break;
case 5:
ws.TestWrite(win.WsHandle(),9999,NULL,0);
break;
case 6:
ws.TestWrite(group.WsHandle(),9999,NULL,0);
break;
case 7:
{
RWsSprite sprite(ws);
sprite.Construct(win,TPoint(0,0),0);
ws.TestWrite(sprite.WsHandle(),9999,NULL,0);
}
break;
default:
return(EWsExitReasonFinished);
}
ws.Flush();
return(EWsExitReasonBad);
}
TInt DoGraphicsPanicTest(RWsSession& aWs, RWindow& aRWin, RDrawableWindow* aDrawWin, CWindowGc* aGc, CFbsFont* aFont, TInt aTest, TInt aSubTest, TBool aInRedraw, TBool aNeedsValidating)
{
if (aInRedraw || aNeedsValidating)
{
aRWin.BeginRedraw();
if (!aInRedraw)
{ // TransWin without redraw active needs the begin/end to make the redraw store active
aRWin.EndRedraw(); // or else all graphics will simply be ignored and no panics will occur
}
}
aWs.Flush();
TRect rect01(0,0,1,1);
TPoint point00;
switch(aTest)
{
case 1:
aGc->UseFont(aFont);
switch(aSubTest)
{
case 0:
{
TWsGcCmdBoxText boxText(rect01,0,CGraphicsContext::ELeft,0,0x800000,1);
aWs.TestWrite(aGc->WsHandle(),EWsGcOpDrawBoxText,&boxText,sizeof(boxText));
}
break;
case 1:
{
TWsGcCmdDrawText dt(point00,600);
aWs.TestWrite(aGc->WsHandle(),EWsGcOpDrawText,&dt,sizeof(dt));
}
break;
case 2:
{
TWsGcCmdBoxTextOptimised1 dt(rect01,0,600);
aWs.TestWrite(aGc->WsHandle(),EWsGcOpDrawBoxTextOptimised1,&dt,sizeof(dt));
}
break;
case 3:
{
TWsGcCmdDrawTextVertical dt(point00,600,EFalse);
aWs.TestWrite(aGc->WsHandle(),EWsGcOpDrawTextVertical,&dt,sizeof(dt));
}
break;
case 4:
{
TWsGcCmdBoxTextVertical dt(rect01);
dt.length=600;
aWs.TestWrite(aGc->WsHandle(),EWsGcOpDrawBoxTextVertical,&dt,sizeof(dt));
}
break;
case 5:
return(EWsExitReasonFinished);
}
break;
case 2:
{
TInt opcode=0;
switch(aSubTest)
{
case 0:
opcode=EWsGcOpGdiBlt2;
break;
case 1:
opcode=EWsGcOpGdiWsBlt2;
break;
case 2:
return(EWsExitReasonFinished);
}
TWsGcCmdGdiBlt2 gdiBlit(point00,0xBADBAD);
aWs.TestWrite(aGc->WsHandle(),opcode,&gdiBlit,sizeof(gdiBlit));
if (aInRedraw)
{ // Adding two bad bitmaps to redraw store fbs store causes leave as NULL handles of failed bitmaps clash
gdiBlit.handle=0xBADBAD2;
aWs.TestWrite(aGc->WsHandle(),opcode,&gdiBlit,sizeof(gdiBlit));
}
}
break;
case 3:
{
const TInt KNumBadBmpModes=3;
const TInt KNumTestsPerOpcode=KNumBadBmpModes*2;
enum {KPanicIndexMasked,KPanicIndexDraw,KPanicIndexAlphaBlend,KPanicIndexMax};
TInt opcodeMode=aSubTest/KNumTestsPerOpcode;
TInt bmpMode=aSubTest%KNumTestsPerOpcode;
TInt bmp1=0xBADBAD;
TInt bmp2=0xBADBAD;
TInt goodBmp;
TInt opcodeBlt;
TInt opcodeDraw;
if (bmpMode<KNumBadBmpModes)
{ // These two use a CFbsBitmap
CFbsBitmap* goodBitmap=new(ELeave) CFbsBitmap;
goodBitmap->Create(TSize(10,10),EGray4);
goodBmp=goodBitmap->Handle();
opcodeBlt=EWsGcOpGdiBltMasked;
opcodeDraw=EWsGcOpDrawBitmapMasked;
}
else
{ // These two use a CWsBitmap
CWsBitmap* goodBitmap=new(ELeave) CWsBitmap(aWs);
goodBitmap->Create(TSize(10,10),EGray4);
goodBmp=goodBitmap->WsHandle();
opcodeBlt=EWsGcOpGdiWsBltMasked;
opcodeDraw=EWsGcOpWsDrawBitmapMasked;
}
switch(bmpMode%KNumBadBmpModes)
{
case 0:
bmp2=goodBmp;
break;
case 1:
bmp1=goodBmp;
break;
case 2: // Leave them both bad
break;
}
switch(opcodeMode)
{
case KPanicIndexMasked:
{
TWsGcCmdBltMasked gdiBlitMasked(point00,bmp1,rect01,bmp2,EFalse);
aWs.TestWrite(aGc->WsHandle(),opcodeBlt,&gdiBlitMasked,sizeof(gdiBlitMasked));
}
break;
case KPanicIndexDraw:
{
TWsGcCmdDrawBitmapMasked maskedBitmap(rect01,bmp1,rect01,bmp2,EFalse);
aWs.TestWrite(aGc->WsHandle(),opcodeDraw,&maskedBitmap,sizeof(maskedBitmap));
}
break;
case KPanicIndexAlphaBlend:
{
TWsGcCmdAlphaBlendBitmaps alphaBlend(point00,bmp1,rect01,bmp2,point00);
aWs.TestWrite(aGc->WsHandle(),EWsGcOpGdiAlphaBlendBitmaps,&alphaBlend,sizeof(alphaBlend));
}
break;
case KPanicIndexMax:
return(EWsExitReasonFinished);
}
}
break;
case 4:
switch(aSubTest)
{
case 0:
{
TWsClCmdCreateBitmap createBitmap;
createBitmap.handle=0xB0D;
aWs.TestWrite(aWs.WsHandle(),EWsClOpCreateBitmap,&createBitmap,sizeof(createBitmap));
}
break;
case 1:
{
TInt badBrush=0xBADB3054;
aWs.TestWrite(aGc->WsHandle(),EWsGcOpUseBrushPattern,&badBrush,sizeof(badBrush));
}
break;
case 2:
{
TWsGcCmdDrawBitmap drawBitmap(point00,0xBADBAD);
aWs.TestWrite(aGc->WsHandle(),EWsGcOpDrawBitmap,&drawBitmap,sizeof(drawBitmap));
}
break;
case 3:
return(EWsExitReasonFinished);
}
break;
case 5:
// test bad opcodes
{
TInt opcode=0;
switch(aSubTest)
{
case 0:
opcode=9999;
break;
case 1:
return(EWsExitReasonFinished);
}
aWs.TestWrite(aGc->WsHandle(),opcode,NULL,0);
}
break;
case 6:
{// Test EWsGcOpDrawPolygon with invalid parameters
// First two times has slightly more points specified than exist in the data
// Third time time has a massive number of points in the header
const TInt KNumTestsPerPolyMode=3;
enum TPanicPolyMode {EPanicPolyModePolygon,EPanicPolyModePolyLine,EPanicPolyModeEnd};
TInt polyMode=aSubTest/KNumTestsPerPolyMode;
if (polyMode==EPanicPolyModeEnd)
return(EWsExitReasonFinished);
TInt subMode=aSubTest%KNumTestsPerPolyMode;
TInt bufPoints=0;
TInt headerPoints=1;
switch(subMode)
{
case 0:
break;
case 1:
bufPoints=2;
headerPoints=8;
break;
case 2:
bufPoints=2;
headerPoints=999999;
break;
}
TInt bufDataLen=bufPoints*sizeof(TPoint);
if (polyMode==EPanicPolyModePolyLine)
bufDataLen+=sizeof(TWsGcCmdDrawPolyLine);
else
bufDataLen+=sizeof(TWsGcCmdDrawPolygon);
TAny* bufData=User::AllocL(bufDataLen);
TPoint* pointPtr;
TInt opcode;
if (polyMode==EPanicPolyModePolyLine)
{
TWsGcCmdDrawPolyLine* drawPolyline=static_cast<TWsGcCmdDrawPolyLine*>(bufData);
drawPolyline->numPoints=headerPoints;
drawPolyline->more=EFalse;
drawPolyline->last=point00;
pointPtr=reinterpret_cast<TPoint*>(drawPolyline+1);
opcode=EWsGcOpDrawPolyLine;
}
else
{
TWsGcCmdDrawPolygon* drawPolygon=static_cast<TWsGcCmdDrawPolygon*>(bufData);
drawPolygon->numPoints=headerPoints;
drawPolygon->fillRule=CGraphicsContext::EAlternate;
pointPtr=reinterpret_cast<TPoint*>(drawPolygon+1);
opcode=EWsGcOpDrawPolygon;
}
const TPoint* endPtr=pointPtr+bufPoints;
TInt pointPos=0;
while(pointPtr<endPtr)
*pointPtr++=TPoint(pointPos,pointPos);
aWs.TestWrite(aGc->WsHandle(),opcode,bufData,bufDataLen);
aWs.Flush(); // Needs flush to make sure EndRedraw() doesn't make buffer bigger and catch out buf len check
}
break;
case 7:
{
// first sets the index to match the total count
// second sets the index negative
// fourth sends too much data
TWsGcCmdStartSegmentedDrawPolygon startPoly;
startPoly.totalNumPoints=8;
aWs.TestWrite(aGc->WsHandle(),EWsGcOpStartSegmentedDrawPolygon,&startPoly,sizeof(startPoly));
TInt bufDataLen=sizeof(TWsGcCmdSegmentedDrawPolygonData)+startPoly.totalNumPoints*sizeof(TPoint);
TAny* bufData=User::AllocL(bufDataLen);
TWsGcCmdSegmentedDrawPolygonData* polyData=static_cast<TWsGcCmdSegmentedDrawPolygonData*>(bufData);
polyData->numPoints=1;
polyData->index=0;
switch(aSubTest)
{
case 0:
polyData->index=startPoly.totalNumPoints;
break;
case 1:
polyData->index=-123;
break;
case 2:
polyData->numPoints=startPoly.totalNumPoints+1;
break;
case 3:
return(EWsExitReasonFinished);
}
aWs.TestWrite(aGc->WsHandle(),EWsGcOpSegmentedDrawPolygonData,polyData,bufDataLen);
TWsGcCmdDrawSegmentedPolygon drawit;
drawit.fillRule=CGraphicsContext::EAlternate;
aWs.TestWrite(aGc->WsHandle(),EWsGcOpDrawSegmentedPolygon,&drawit,sizeof(drawit));
}
break;
case 8:
{
if (aSubTest==1)
return(EWsExitReasonFinished);
// This is a test designed to specificially test polylines still work after the previous
// polyline/polygon tests. One potential defect is they leave the common redraw store gc
// in a bad state still holding part of the poly data and causing a EWservPanicBadPolyData
// panic.
// This test is designed to make sure the drawpolyline call works ok and we reach the bad
// opcode panic instead.
TWsGcCmdStartSegmentedDrawPolygon startPoly;
startPoly.totalNumPoints=2;
aWs.TestWrite(aGc->WsHandle(),EWsGcOpStartSegmentedDrawPolygon,&startPoly,sizeof(startPoly));
struct
{
TWsGcCmdSegmentedDrawPolygonData iPolyData;
TPoint iPoints[2];
} polyParams;
polyParams.iPoints[0].iX=1;
polyParams.iPoints[0].iY=1;
polyParams.iPoints[1].iX=2;
polyParams.iPoints[1].iY=2;
polyParams.iPolyData.numPoints=2;
polyParams.iPolyData.index=0;
aWs.TestWrite(aGc->WsHandle(),EWsGcOpSegmentedDrawPolygonData,&polyParams.iPolyData,sizeof(polyParams));
TWsGcCmdDrawSegmentedPolygon drawit;
drawit.fillRule=CGraphicsContext::EAlternate;
aWs.TestWrite(aGc->WsHandle(),EWsGcOpDrawSegmentedPolygon,&drawit,sizeof(drawit));
aWs.TestWrite(aGc->WsHandle(),9999,NULL,0);
}
break;
case 9:
if (aSubTest==1)
return(EWsExitReasonFinished);
aGc->Activate(*aDrawWin); // Double activate
break;
case 10:
if (aSubTest==1)
return(EWsExitReasonFinished);
aGc->DrawText(_L("No font"),point00);
break;
case 11:
if (aSubTest==1)
return(EWsExitReasonFinished);
aGc->SetBrushStyle(CGraphicsContext::EPatternedBrush);
aGc->DrawRect(rect01);
break;
case 12:
{
if (aSubTest==1)
return(EWsExitReasonFinished);
aGc->UseFont(aFont);
TPtrC bigAndbad(NULL,5000); // Will go through remote descriptor fetching code
aGc->DrawText(bigAndbad,point00);
}
break;
case 13:
{
if (aSubTest==1)
return(EWsExitReasonFinished);
TInt badHandle=0xDEADBAD;
aWs.TestWrite(aGc->WsHandle(),EWsGcOpUseFont,&badHandle,sizeof(badHandle));
aGc->DrawText(_L("BOO!"),point00);
}
break;
}
if (aInRedraw)
aRWin.EndRedraw();
aWs.Finish();
return(EWsExitReasonBad);
}
LOCAL_C TInt GraphicsPanicTest(TInt aInt, TAny* aPanicParams)
{
CTPanic::TPanicParams* panicParams=static_cast<CTPanic::TPanicParams*>(aPanicParams);
/*
* Drawing to a transparent window goes via the redraw store. In this
* situation parameters do not get checked during the original processing
* of the incoming graphics commands. They are only caught later when
* playing back from the redraw store.
*/
const TBool useTransWin = panicParams->iRedrawMode==EPanicRedrawModeTransRedraw;
/*
* We always do redraw drawing unless we are using a BackedUpWindow.
* Redraws can affect the way graphics commands are pre-processed,
* as with transparent windows they can also cause commands to get
* buffered in the redraw store and played back later.
*/
const TBool inRedraw =
panicParams->iRedrawMode==EPanicRedrawModeNormalRedraw ||
panicParams->iRedrawMode==EPanicRedrawModeTransRedraw ||
panicParams->iRedrawMode==EPanicRedrawModeInvisRedraw;
/*
* Drawing to an invisible window skips some of the code where errors
* are caught. Particularly text drawing commands that skip the actual
* drawing, but still process the update of the justification, this
* has the potential of missing parameter checks made during the actual
* drawing, but being caught out when processing the justification update.
*/
const TBool invisWin = panicParams->iRedrawMode==EPanicRedrawModeInvisRedraw;
RWsSession ws;
User::LeaveIfError(ws.Connect());
CWsScreenDevice* scrdev=new(ELeave) CWsScreenDevice(ws);
User::LeaveIfError(scrdev->Construct(panicParams->iScreen));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(888));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
RDrawableWindow* drawWin;
RWindow rwin(ws);
RBackedUpWindow bwin(ws);
TBool needsValidating=EFalse;
if (useTransWin || inRedraw || invisWin)
{
drawWin=&rwin;
needsValidating=ETrue;
User::LeaveIfError(rwin.Construct(group,1));
if (useTransWin)
{
rwin.SetTransparencyAlphaChannel();
}
}
else
{
// EPanicRedrawModeBackedUpWindow case
drawWin=&bwin;
User::LeaveIfError(bwin.Construct(group, EGray4, 1));
}
const TSize testWinSize(100,100);
User::LeaveIfError(drawWin->SetSizeErr(testWinSize));
if (invisWin)
drawWin->SetPosition(TPoint(-testWinSize.iWidth,-testWinSize.iHeight));
drawWin->Activate();
CWindowGc* gc;
scrdev->CreateContext(gc);
gc->Activate(*drawWin);
CFbsFont* font;
User::LeaveIfError(scrdev->GetNearestFontToDesignHeightInTwips((CFont*&)font,TFontSpec()));
TInt ret=DoGraphicsPanicTest(ws,rwin,drawWin,gc,font,aInt,panicParams->iSubTest,inRedraw,needsValidating);
if (ret!=EWsExitReasonFinished && invisWin)
{
/*
* Some functions are totally skipped on invisible windows, parameter
* errors will be harmlessly ignored in these case. To make the test
* pass we re-do the tests with the window now visible. The purpose
* of the invisible draw tests was not to check the client is always
* panicked doing illegal draws to invisible windows, but to make sure
* they had no harmful side effects.
*/
drawWin->SetPosition(TPoint(0,0));
gc->Reset();
ret=DoGraphicsPanicTest(ws,rwin,drawWin,gc,font,aInt,panicParams->iSubTest,inRedraw,needsValidating);
}
return(ret);
}
LOCAL_C TInt DoMiscPanicTest(TInt aSubTest, TAny* )
{
const TInt KNumPanicFuncsPerMode=EWsClOpLastEnumValue;
const TInt KNumPanicFuncModes=6;
const TInt KNumPanicSendTests=KNumPanicFuncsPerMode*KNumPanicFuncModes;
const TInt KNumRandGarbageTests=500;
if (aSubTest==(KNumPanicSendTests+KNumRandGarbageTests))
return(EWsExitReasonFinished);
RWsSessionHacker wshacker;
User::LeaveIfError(wshacker.Connect());
if (aSubTest<KNumPanicSendTests)
{
TInt messageMode=aSubTest/KNumPanicFuncsPerMode;
TInt msgFunc=aSubTest%KNumPanicFuncsPerMode;
const TInt EPanicWservMessAsynchronousService=0x010000; //copy of EWservMessAsynchronousService
const TInt EPanicWservMessAnimDllAsyncCommand=0x100000; //copy of EWservMessAnimDllAsyncCommand
switch(messageMode%3)
{
case 0:
if(msgFunc == EWservMessFinish) //RWsSession::Finish() doesn't panic
User::Panic(KWSERV, 0); //simulate a "successful" wserv panic to skip the sub test
break;
case 1:
msgFunc|=EPanicWservMessAsynchronousService;
break;
case 2:
msgFunc|=EPanicWservMessAnimDllAsyncCommand;
break;
}
TInt sendItErr=KErrNone;
if (messageMode<3)
{
if (msgFunc&EPanicWservMessAsynchronousService)
{
wshacker.PanicItSend(msgFunc);
// Async request, probably won't panic, we just want to make sure nothing crashes 'orribly
// So do it again without the async bit and let normal handling cause the panic
msgFunc&=~EPanicWservMessAsynchronousService;
}
sendItErr=wshacker.PanicItSendReceive(msgFunc);
}
else
{
TPtrC8 badDesc(reinterpret_cast<const TUint8*>(0xDEAD),100);
TIpcArgs ipcArgs;
ipcArgs.Set(0,&badDesc);
if (msgFunc&EPanicWservMessAsynchronousService)
{
sendItErr=wshacker.PanicItSend(msgFunc,ipcArgs);
msgFunc&=~EPanicWservMessAsynchronousService;
}
sendItErr=wshacker.PanicItSendReceive(msgFunc,ipcArgs);
}
if (sendItErr==KErrNotSupported)
wshacker.PanicItSendReceive(EWservMessCommandBuffer); // Should always panic
}
else
{
// Fill Wserv buffer with random garbage
RWsBufferHacker* hacker=reinterpret_cast<RWsBufferHacker*>(wshacker.WsBuffer());
TInt64 seed=aSubTest;
TInt retries=0;
const TInt KMaxRandPanicRetrys=1000;
do
{
const TInt maxLen=hacker->iBuf.MaxLength()-1;
TInt writeLen=1+Math::Rand(seed)%maxLen;
while(writeLen--)
{
TUint8 randData=static_cast<TUint8>(Math::Rand(seed));
hacker->iBuf.Append(randData);
}
wshacker.Flush();
retries++;
} while(retries<KMaxRandPanicRetrys);
}
return(EWsExitReasonBad);
}
LOCAL_C TInt DoCMPanicTest(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// use correct screen
//
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
switch(aInt)
{
case 1:
ws.ComputeMode((RWsSession::TComputeMode)543);
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
#if defined(_DEBUG) && defined(__WINS__)
LOCAL_C TInt DoCKPanicTest(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// use correct screen
//
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
group.Construct(888);
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
switch(aInt)
{
case 1:
group.CancelCaptureKey(345);
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
#endif
LOCAL_C TInt DoEventPanicTest(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// use correct screen
//
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
switch(aInt)
{
case 1:
TRequestStatus stat;
ws.EventReady(&stat);
ws.EventReady(&stat);
User::After(15000000); //15secs
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
LOCAL_C TInt DoTBufPtrTests(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// use correct screen
//
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
switch(aInt)
{
case 1:
{
TWsClCmdLoadAnimDll dt;
dt.length=600;
ws.TestWrite(ws.WsHandle(),EWsClOpCreateAnimDll,&dt,sizeof(dt));
}
break;
case 2:
{
TInt len=600;
ws.TestWrite(ws.WsHandle(),EWsClOpLogMessage,&len,sizeof(len));
}
break;
case 3:
{
RWindowGroup group(ws);
group.Construct(888);
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
TWsWinCmdSetName dt;
dt.length=600;
dt.ptr=NULL;
ws.TestWrite(group.WsHandle(),EWsWinOpSetName,&dt,sizeof(dt));
}
break;
case 4:
{
RWindowGroup group(ws);
group.Construct(888);
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
TWsWinCmdSetName dt;
dt.length=600;
dt.ptr=(TDesC *)0x1234;
ws.TestWrite(group.WsHandle(),EWsWinOpSetName,&dt,sizeof(dt));
}
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
#if defined(_DEBUG) && defined(__WINS__)
LOCAL_C TInt DoMismatchedCancelCaptureTest(TInt aInt, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// use correct screen
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(888));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
RWindow win(ws);
User::LeaveIfError(win.Construct(group, 1));
win.Activate();
TInt capture;
switch (aInt)
{
case CTPanic::ECancelCaptureKey:
// Create a capture that is not matched to CancelCaptureKey()
capture = group.CaptureLongKey(' ','a',0,0,2,ELongCaptureNormal);
ws.Flush();
group.CancelCaptureKey(capture);
break;
case CTPanic::ECancelCaptureKeyUpAndDowns:
// Create a capture that is not matched to CancelCaptureKeyUpAndDowns()
capture = group.CaptureKey('A',0,0);
ws.Flush();
group.CancelCaptureKeyUpAndDowns(capture);
break;
case CTPanic::ECancelCaptureLongKey:
// Create a capture that is not matched to CancelCaptureLongKey()
capture = group.CaptureKeyUpAndDowns(EStdKeySpace,0,0);
ws.Flush();
group.CancelCaptureLongKey(capture);
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
#endif // _DEBUG
class ROverrideProtectionInRSessionBase : public RWsSession
{
public:
inline TInt SendReceive(TInt aFunction,TAny *aPtr) const {return(RSessionBase::SendReceive(aFunction,TIpcArgs(aPtr)));};
};
LOCAL_C TInt DoMultiInitPanicTest(TInt , TAny *aScreenNumber)
{
ROverrideProtectionInRSessionBase ws;
User::LeaveIfError(ws.Connect());
// use correct screen
//
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
group.Construct(888);
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
ws.Flush();
ws.SendReceive(EWservMessInit,NULL);
return(EWsExitReasonBad);
}
LOCAL_C TInt DoSpritePanicTestL(TInt aTest, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// use correct screen
//
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(889));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
RBlankWindow win(ws);
User::LeaveIfError(win.Construct(group,898));
RWsPointerCursor* cursor=(RWsPointerCursor*)&win;
switch (aTest)
{
case 1:
win.SetCustomPointerCursor(*cursor);
break;
case 2:
ws.SetSystemPointerCursor(*cursor,0);
break;
case 3:
{
RAnimDll animDll=RAnimDll(ws);
User::LeaveIfError(animDll.Load(KAnimDLLName));
RTestAnim anim=RTestAnim(animDll);
RWsSprite* sprite=(RWsSprite*)&win;
User::LeaveIfError(anim.Construct(*sprite,EAnimTypeSprite,TPtrC8()));
}
break;
case 4:
{
CFbsBitmap* bitmap=new(ELeave) CFbsBitmap;
CleanupStack::PushL(bitmap);
User::LeaveIfError(bitmap->Load(TEST_BITMAP_NAME,0));
win.SetExtent(TPoint(),TSize(150,250));
win.SetVisible(ETrue);
win.Activate();
RWsSprite sprite(ws);
User::LeaveIfError(sprite.Construct(win,TPoint(),0));
TSpriteMember member;
member.iMaskBitmap=NULL;
member.iInvertMask=EFalse;
member.iDrawMode=CGraphicsContext::EDrawModePEN;
member.iOffset=TPoint();
member.iInterval=TTimeIntervalMicroSeconds32(0);
member.iBitmap=bitmap;
User::LeaveIfError(sprite.AppendMember(member));
User::LeaveIfError(sprite.Activate());
User::After(1000000); //1 sec
User::LeaveIfError(bitmap->Resize(bitmap->SizeInPixels() + TSize(200,200)));
User::After(1000000); //1 sec
CleanupStack::Pop(bitmap);
break;
}
}
ws.Flush();
return(EWsExitReasonBad);
}
#ifdef __WINS__
LOCAL_C TInt DoDoubleConstructionTestL(TInt aTest, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// use correct screen
//
CWsScreenDevice* screen = new(ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(890, EFalse));
RBlankWindow bwin(ws);
User::LeaveIfError(bwin.Construct(group,900));
switch (aTest)
{
case 1:
{
RWsSprite sprite = RWsSprite(ws);
User::LeaveIfError(sprite.Construct(bwin,TPoint(),0));
sprite.Construct(bwin,TPoint(),0); //should panic
sprite.Close();
}
break;
case 2:
{
RWsPointerCursor cursor(ws);
User::LeaveIfError(cursor.Construct(0));
cursor.Construct(0); //should panic
cursor.Close();
}
break;
case 3:
{
RSoundPlugIn click(ws);
User::LeaveIfError(click.Construct());
click.Construct(); //should panic
click.Close();
}
break;
case 4:
{
RWindowGroup windowgroup(ws);
User::LeaveIfError(windowgroup.Construct(901));
windowgroup.Construct(902); //should panic
windowgroup.Close();
}
break;
case 5:
{
RWindow win(ws);
User::LeaveIfError(win.Construct(group,902));
win.Construct(group,903); //should panic
win.Close();
}
break;
case 6:
{
RBlankWindow win(ws);
User::LeaveIfError(win.Construct(group,902));
win.Construct(group,903); //should panic
win.Close();
}
break;
case 7:
{
RBackedUpWindow win(ws);
User::LeaveIfError(win.Construct(group,EGray4,902));
win.Construct(group,EGray4,903); //should panic
win.Close();
}
break;
case 8:
{
RAnimDll animDll=RAnimDll(ws);
User::LeaveIfError(animDll.Load(KAnimDLLName));
animDll.Load(KAnimDLLName); //should panic
animDll.Close();
}
break;
case 9:
{
CWindowGc *gc = new(ELeave) CWindowGc(screen);
User::LeaveIfError(gc->Construct());
gc->Construct(); //should panic
delete gc;
}
break;
case 10:
{
CWsScreenDevice* screendevice = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screendevice->Construct());
screendevice->Construct(); //should panic
delete screendevice;
}
break;
default:
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
#endif
/** Checks that activating a sprite without members will panic.
*/
LOCAL_C TInt DoTestSpriteActivatePanicL(TInt aTest, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
CWsScreenDevice* screen = new(ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(891, EFalse, screen));
RBlankWindow bwin(ws);
User::LeaveIfError(bwin.Construct(group,892));
switch(aTest)
{
case 1:
{
RWsSprite sprite = RWsSprite(ws);
User::LeaveIfError(sprite.Construct(group,TPoint(),0));
sprite.Activate(); //should panic here
sprite.Close();
}
break;
case 2:
{
RWsSprite sprite = RWsSprite(ws);
User::LeaveIfError(sprite.Construct(bwin,TPoint(),0));
sprite.Activate(); //should panic here
sprite.Close();
}
break;
}
return(EWsExitReasonBad);
}
LOCAL_C TInt DoMoveToGroupPanicTestL(TInt aTest, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// use correct screen
//
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(887));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
TInt id=group.Identifier();
switch (aTest)
{
case 1:
{
RWindowTreeNode* win=&group;
((RWindowBase*)win)->MoveToGroup(id);
}
break;
case 2:
{
RBlankWindow win1(ws);
User::LeaveIfError(win1.Construct(group,878));
RBlankWindow win2(ws);
User::LeaveIfError(win2.Construct(win1,788));
win2.MoveToGroup(id);
}
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
LOCAL_C TInt DoGetEventPanicTestL(TInt aTest, TAny *aScreenNumber)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
switch(aTest)
{
case 1:
{
TPckgBuf<TWsEvent> event;
ws.TestWrite(ws.WsHandle(),EWsClOpGetEvent,&event,0);
}
break;
case 2:
{
CWsScreenDevice* screen=new(ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(555)); // trigger a focus changed event
TRequestStatus stat;
ws.EventReady(&stat);
User::WaitForRequest(stat);
TPtrC8 badDesc(reinterpret_cast<const TUint8*>(0xDEAD),100);
ws.TestWrite(ws.WsHandle(),EWsClOpGetEvent,&badDesc,0);
}
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
LOCAL_C TInt DoWinHandlePanicTestL(TInt aTest, TAny *)
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
RWindowGroup group1(ws);
RWindowGroup group2(ws);
RWindow win1(ws);
RWindow win2(ws);
switch(aTest)
{
case 1:
User::LeaveIfError(group1.Construct(888));
User::LeaveIfError(group2.Construct(888));
break;
case 2:
User::LeaveIfError(group1.Construct(777));
User::LeaveIfError(win1.Construct(group1,888));
User::LeaveIfError(win2.Construct(group1,888));
break;
case 3:
User::LeaveIfError(group1.Construct(777));
User::LeaveIfError(win1.Construct(group1,777));
break;
case 4:
User::LeaveIfError(group1.Construct(777));
User::LeaveIfError(win1.Construct(group1,0));
break;
}
ws.Flush();
return(EWsExitReasonBad);
}
#ifdef __WINS__
LOCAL_C TInt DoDeleteScreenPanicTestL(TInt aTest, TAny *aScreenNumber)
/**
* Test examples of use of the 'screen device deleted' panic for group windows.
* This is issued to panic the client, if they make API calls to RWindowGroup after having deleted
* the CWsScreenDevice with which that window group is associated.
*/
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
// point to correct screen
CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
User::LeaveIfError(screen->Construct((TInt)aScreenNumber));
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(888));
group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close
switch(aTest)
{
// Test 1: deleting screen then modifying screen change events is illegal
case 1:
{
delete screen, screen=NULL;
group.EnableScreenChangeEvents();
break;
}
// Test 2: deleting screen then setting window group name is illegal
case 2:
{
delete screen, screen=NULL;
_LIT(KPanicTest, "PanicTest");
group.SetName(KPanicTest);
break;
}
}
ws.Flush();
return(EWsExitReasonBad);
}
#endif
LOCAL_C TInt DoUnInitPanicTest(TInt , TAny *)
{
// Creating a client session outside the test harness for panicking
// before initialisation as the test harness initialises the one it creates.
TVersion version(0,0,0);
_LIT(KServerName, "!Windowserver");
RUnInitalisedConnect myUnInit;
User::LeaveIfError(myUnInit.Connect(KServerName(), version));
myUnInit.Send(EWservMessCommandBuffer);
return(EWsExitReasonBad);
}
void CTPanic::TestScreenDevicePanicsL()
{
TEST(iTest->TestWsPanicL(&DoScreenDevicePanicTest,EWservPanicBitmap,1,(TAny*)iTest->iScreenNumber));
TEST(iTest->TestWsPanicL(&DoScreenDevicePanicTest,EWservPanicBitmap,2,(TAny*)iTest->iScreenNumber));
}
void CTPanic::TestMiscPanicsL()
{
TBool finished=EFalse;
TInt index=0;
while(!finished)
{
const TBool result = iTest->TestWsPanicL(&DoMiscPanicTest, EWservNoPanic, index, NULL, &finished);
if(!result)
{
INFO_PRINTF2(_L("TestMiscPanicsL %d failed"), index);
TEST(result);
}
index++;
}
}
void CTPanic::LogHeapInfo()
{
_LIT(KInfoHeapSummary," WsHeap - Count=%d,Total=%d,Free=%d,Max free=%d");
TPckgBuf<TWsDebugHeapInfo> heapInfo;
TheClient->iWs.DebugInfo(EWsDebugInfoHeap,heapInfo);
TBuf<256> infoBuf;
infoBuf.Format(KInfoHeapSummary,heapInfo().iCount,heapInfo().iTotal,heapInfo().iAvailable,heapInfo().iLargestAvailable);
INFO_PRINTF1(infoBuf);
}
void CTPanic::TestGraphicsPanicsL(TClientPanic aExitReason, TInt aIndex, CTPanic::TPanicParams* aPanicParams)
{
TBool finished=EFalse;
aPanicParams->iSubTest=0;
// uncomment to show which test is being run
INFO_PRINTF3(_L("GraphicsPanicTest %d, mode=%d"),aIndex,aPanicParams->iRedrawMode);
RDebug::Print(_L("GraphicsPanicTest %d, mode=%d"),aIndex,aPanicParams->iRedrawMode);
do
{
// uncomment for detailed view of which sub-test failed
LogHeapInfo();
INFO_PRINTF4(_L("GraphicsPanicTest %d/%d, mode=%d"),aIndex,aPanicParams->iSubTest,aPanicParams->iRedrawMode);
RDebug::Print(_L("GraphicsPanicTest %d/%d, mode=%d"),aIndex,aPanicParams->iSubTest,aPanicParams->iRedrawMode);
TEST(iTest->TestWsPanicL(&GraphicsPanicTest,aExitReason,aIndex,aPanicParams,&finished));
aPanicParams->iSubTest++;
} while(!finished);
iTest->CloseAllPanicWindows();
}
void CTPanic::TestGraphicsPanicsL(TPanicRedrawMode aRedrawMode)
{
CTPanic::TPanicParams pp;
pp.iScreen=iTest->iScreenNumber;
pp.iRedrawMode=aRedrawMode;
static TClientPanic expectedPanics[]=
{
EWservPanicBufferPtr,
EWservPanicBitmap,
EWservPanicBitmap,
EWservPanicBitmap,
EWservPanicOpcode,
EWservPanicBadPolyData,
EWservPanicBadPolyData,
EWservPanicOpcode,
EWservPanicGcActive,
EWservPanicNoFont,
EWservPanicNoBrush,
EWservPanicDescriptor,
EWservPanicFont,
EWservNoPanic, // Marks the end of the list
};
TInt panicIndex=0;
TClientPanic expectedPanic;
while((expectedPanic=expectedPanics[panicIndex++])!=EWservNoPanic)
{
TestGraphicsPanicsL(expectedPanic,panicIndex,&pp);
}
}
void CTPanic::TestGraphicsPanicsL()
{
TestGraphicsPanicsL(EPanicRedrawModeBackedUpWindow);
TestGraphicsPanicsL(EPanicRedrawModeNormalRedraw);
if (TransparencySupportedL()==KErrNone)
{
TestGraphicsPanicsL(EPanicRedrawModeTransRedraw);
}
TestGraphicsPanicsL(EPanicRedrawModeInvisRedraw);
}
void CTPanic::TestDeletedParentPanicsL()
{
TEST(iTest->TestWsPanicL(&DoDeletedParentTest,EWservPanicParentDeleted,1,(TAny*)iTest->iScreenNumber));
}
void CTPanic::TestHandleReUseL()
{
for (TInt ii=2;ii<6;++ii)
{
TEST(iTest->TestWsPanicL(&DoHandleReUse,EWservPanicHandle,ii,(TAny*)iTest->iScreenNumber));
}
}
void CTPanic::TestComputeModePanicsL()
{
TEST(iTest->TestWsPanicL(&DoCMPanicTest,EWservPanicSetComputeMode,1,(TAny*)iTest->iScreenNumber));
}
void CTPanic::TestCaptureKeyPanicsL()
{
// Run this test in debug on emulator only.
// On a debug ROM the release version of the wserv.exe is included so the test can't be run as no panic happens.
#if defined(_DEBUG) && defined(__WINS__)
TEST(iTest->TestWsPanicL(&DoCKPanicTest,EWservPanicDestroy,1,(TAny*)iTest->iScreenNumber));
#endif
}
void CTPanic::TestEventPanicsL()
{
TEST(iTest->TestWsPanicL(&DoEventPanicTest,EWservPanicReadOutstanding,1,(TAny*)iTest->iScreenNumber));
}
void CTPanic::TestTPtrPanicsL()
{
TEST(iTest->TestWsPanicL(&DoTBufPtrTests,EWservPanicBufferPtr,1,(TAny*)iTest->iScreenNumber));
}
void CTPanic::TestOpcodePanicsL()
{
TInt param=1;
TBool finishTest = EFalse;
while(!finishTest)
{
TEST(iTest->TestWsPanicL(&DoOpcodeTests,EWservPanicOpcode,param,(TAny*)iTest->iScreenNumber,&finishTest));
param++;
}
}
void CTPanic::TestMultiInitPanicL()
{
TEST(iTest->TestWsPanicL(&DoMultiInitPanicTest,EWservPanicReInitialise,0,(TAny*)iTest->iScreenNumber));
}
/**
@SYMTestCaseID GRAPHICS-WSERV-0472
@SYMDEF DEF118618
@SYMTestCaseDesc Test defect fixes to system panics
@SYMTestPriority High
@SYMTestStatus Implemented
@SYMTestActions Check that various defect fixes to system panics are correct.
Also verify that reconstructing a closed object will succeed.
@SYMTestExpectedResults Panics respond correctly
*/
void CTPanic::TestDoubleConstructionL()
{
#ifdef __WINS__
for(TInt test=1;test<11;test++)
{
TEST(iTest->TestW32PanicL(&DoDoubleConstructionTestL,EW32PanicGraphicDoubleConstruction,test,NULL));
}
TestDoubleConstructionNoPanic();
#endif
}
/** Verifies the following scenario is valid:
1. Create some wserv client-side objects.
2. Call Close on them.
3. Reconstruct them and they shouldn't panic this time. */
void CTPanic::TestDoubleConstructionNoPanic()
{
RWsSession ws;
User::LeaveIfError(ws.Connect());
RWindowGroup group(ws);
User::LeaveIfError(group.Construct(890, EFalse));
RBlankWindow bwin(ws);
User::LeaveIfError(bwin.Construct(group,900));
//RWsSprite
RWsSprite sprite(ws);
TEST(KErrNone == sprite.Construct(bwin,TPoint(0,0),0));
sprite.Close();
TEST(KErrNone == sprite.Construct(bwin,TPoint(0,0),0));
sprite.Close();
//RWsPointerCursor
RWsPointerCursor cursor(ws);
TEST(KErrNone == cursor.Construct(0));
cursor.Close();
TEST(KErrNone == cursor.Construct(0));
cursor.Close();
//RSoundPlugIn
RSoundPlugIn click(ws);
TEST(KErrNone == click.Construct());
click.Close();
TEST(KErrNone == click.Construct());
click.Close();
//RWindowGroup
RWindowGroup windowgroup(ws);
TEST(KErrNone ==windowgroup.Construct(901));
windowgroup.Close();
TEST(KErrNone ==windowgroup.Construct(901));
windowgroup.Close();
//RWindow
RWindow win1(ws);
TEST(KErrNone == win1.Construct(group,902));
win1.Close();
TEST(KErrNone == win1.Construct(group,902));
win1.Close();
//RBlankWindow
RBlankWindow win2(ws);
TEST(KErrNone == win2.Construct(group,902));
win2.Close();
TEST(KErrNone == win2.Construct(group,902));
win2.Close();
//RBackedUpWindow
RBackedUpWindow win3(ws);
TEST(KErrNone == win3.Construct(group,EGray4,902));
win3.Close();
TEST(KErrNone == win3.Construct(group,EGray4,902));
win3.Close();
//RAnimDll
RAnimDll animDll=RAnimDll(ws);
TEST(KErrNone == animDll.Load(KAnimDLLName));
animDll.Close();
TEST(KErrNone == animDll.Load(KAnimDLLName));
animDll.Close();
group.Close();
bwin.Close();
ws.Close();
}
void CTPanic::TestSpritePanicsL()
{
for(TInt test=1;test<4;test++)
{
TEST(iTest->TestWsPanicL(&DoSpritePanicTestL,EWservPanicSprite,test,(TAny*)iTest->iScreenNumber));
}
}
/**
@SYMTestCaseID GRAPHICS-WSERV-0475
@SYMDEF DEF118616
@SYMTestCaseDesc Test defect fixes to system panics
@SYMTestPriority High
@SYMTestStatus Implemented
@SYMTestActions Check that various defect fixes to system panics are correct.
@SYMTestExpectedResults Panics respond correctly
*/
void CTPanic::TestSpriteActivatePanicL()
{
for(TInt test=1;test<3;test++)
{
TEST(iTest->TestWsPanicL(&DoTestSpriteActivatePanicL,EWservPanicNoSpriteMember,test,NULL));
}
}
void CTPanic::TestMoveToGroupPanicsL()
{
TEST(iTest->TestWsPanicL(&DoMoveToGroupPanicTestL,EWservPanicOpcode,1,(TAny*)iTest->iScreenNumber));
TEST(iTest->TestWsPanicL(&DoMoveToGroupPanicTestL,EWservPanicNotTopClient,2,(TAny*)iTest->iScreenNumber));
}
void CTPanic::TestDeleteScreenPanicL()
{
#ifdef __WINS__
TEST(iTest->TestWsPanicL(&DoDeleteScreenPanicTestL,EWservPanicGroupWinScreenDeviceDeleted,1,(TAny*)iTest->iScreenNumber));
TEST(iTest->TestWsPanicL(&DoDeleteScreenPanicTestL,EWservPanicGroupWinScreenDeviceDeleted,2,(TAny*)iTest->iScreenNumber));
#endif
}
void CTPanic::TestWinHandleErrors()
{
#ifdef __WINS__
TEST(iTest->TestWsPanicL(&DoWinHandlePanicTestL,EWservPanicDuplicateHandle,1));
TEST(iTest->TestWsPanicL(&DoWinHandlePanicTestL,EWservPanicDuplicateHandle,2));
TEST(iTest->TestWsPanicL(&DoWinHandlePanicTestL,EWservPanicDuplicateHandle,3));
#endif
TEST(iTest->TestWsPanicL(&DoWinHandlePanicTestL,EWservPanicNullHandle,4));
}
void CTPanic::TestGetEventErrors()
{
TEST(iTest->TestWsPanicL(&DoGetEventPanicTestL,EWservPanicUnsignalledEventData,1,(TAny*)iTest->iScreenNumber));
TEST(iTest->TestWsPanicL(&DoGetEventPanicTestL,EWservPanicDescriptor,2,(TAny*)iTest->iScreenNumber));
}
void CTPanic::TestUnInitPanicL()
{
TEST(iTest->TestWsPanicL(&DoUnInitPanicTest,EWservPanicUninitialisedClient,0,(TAny*)iTest->iScreenNumber));
}
void CTPanic::ConstructL()
{
TheGc->Activate(*BaseWin->Win());
TheGc->Clear();
TheGc->SetBrushColor(TRgb::Gray16(12));
TheGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
TheGc->SetPenStyle(CGraphicsContext::ENullPen);
TheGc->DrawRect(TRect(BaseWin->Win()->Size()));
TheGc->Deactivate();
TheGc->Activate(*TestWin->Win());
TheGc->Clear();
TheGc->SetBrushColor(TRgb::Gray16(4));
TheGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
TheGc->SetPenStyle(CGraphicsContext::ENullPen);
TheGc->DrawRect(TRect(TestWin->Win()->Size()));
TheGc->Deactivate();
//
_LIT(KReportFullRom,"Warning full ROM, EikSrv present, panic dialogs may interfere with tests");
_LIT(KReportGoodRom,"ROM OK, No EikSrv present");
if (iTest->IsFullRomL())
{
INFO_PRINTF1(KReportFullRom);
}
else
{
INFO_PRINTF1(KReportGoodRom);
}
}
void CTPanic::TestAlphaBlendingPanicL()
{
INFO_PRINTF1(_L("Masked transparency support has been removed."));
}
void CTPanic::TestMismatchedCaptureCancelPanicL()
{
// Run this test in debug on emulator only.
// On a debug ROM the release version of the wserv.exe is included so the test can't be run as no panic happens.
#if defined(_DEBUG) && defined(__WINS__)
TEST(iTest->TestWsPanicL(DoMismatchedCancelCaptureTest,EWservPanicDestroy,ECancelCaptureKey,(TAny*)iTest->iScreenNumber));
TEST(iTest->TestWsPanicL(DoMismatchedCancelCaptureTest,EWservPanicDestroy,ECancelCaptureKeyUpAndDowns,(TAny*)iTest->iScreenNumber));
TEST(iTest->TestWsPanicL(DoMismatchedCancelCaptureTest,EWservPanicDestroy,ECancelCaptureLongKey,(TAny*)iTest->iScreenNumber));
#endif
}
void CTPanic::RunTestCaseL(TInt /*aCurTestCase*/)
{
((CTPanicStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
switch(++iTest->iState)
{
/**
@SYMTestCaseID GRAPHICS-WSERV-0259
@SYMDEF DEF081259
@SYMTestCaseDesc Test various system panics
@SYMTestPriority High
@SYMTestStatus Implemented
@SYMTestActions Check that various system panics respond correctly
@SYMTestExpectedResults Panics respond correctly
*/
case 1:
{
((CTPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0259"));
iTest->LogSubTest(_L("TestCaptureKeyPanicsL"));
TestCaptureKeyPanicsL();
}
break;
case 2:
{
iTest->LogSubTest(_L("TestEventPanicsL"));
TestEventPanicsL();
}
break;
case 3:
{
iTest->LogSubTest(_L("TestComputeModePanicsL"));
TestComputeModePanicsL();
}
break;
case 4:
{
#ifdef __WINS__
// Only running this under WINS as the tests are a bit excessive, firing off all sorts of illegal
// opcode/flag combinations, as well as buffers of random data.
// Currently on ARM builds they're failing with KErrOutOfMemory, probably running out of handles
// somewhere in the OS.
iTest->LogSubTest(_L("TestMiscPanicsL"));
TestMiscPanicsL();
#endif
}
break;
case 5:
{
iTest->LogSubTest(_L("TestGraphicsPanicsL"));
TestGraphicsPanicsL();
}
break;
case 6:
{
iTest->LogSubTest(_L("TestTPtrPanicsL"));
TestTPtrPanicsL();
}
break;
case 7:
{
iTest->LogSubTest(_L("TestOpcodePanicsL"));
TestOpcodePanicsL();
}
break;
case 8:
{
iTest->LogSubTest(_L("TestScreenDevicePanicsL"));
TestScreenDevicePanicsL();
}
break;
case 9:
{
iTest->LogSubTest(_L("TestMultiInitPanicL"));
TestMultiInitPanicL();
}
break;
/**
@SYMTestCaseID GRAPHICS-WSERV-0260
@SYMDEF DEF081259
@SYMTestCaseDesc Test various system panics
@SYMTestPriority High
@SYMTestStatus Implemented
@SYMTestActions Check that various system panics respond correctly
@SYMTestExpectedResults Panics respond correctly
*/
case 10:
{
((CTPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0260"));
iTest->LogSubTest(_L("Panic 2"));
TestSpritePanicsL();
TestMoveToGroupPanicsL();
}
break;
/**
@SYMTestCaseID GRAPHICS-WSERV-0261
@SYMDEF DEF081259
@SYMTestCaseDesc Test defect fixes to system panics
@SYMTestPriority High
@SYMTestStatus Implemented
@SYMTestActions Check that various defect fixes to system panics are correct
@SYMTestExpectedResults Panics respond correctly
*/
case 11:
{
((CTPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0261"));
_LIT(KPanicTest,"Defect Fixes (Pan.3)");
iTest->LogSubTest(KPanicTest);
TestDeletedParentPanicsL();
TestHandleReUseL();
TestDeleteScreenPanicL(); // DEF069809
}
break;
/**
@SYMTestCaseID GRAPHICS-WSERV-097969-0001
@SYMDEF DEF097969
@SYMTestCaseDesc Test defect fixes to system panics
@SYMTestPriority High
@SYMTestStatus Implemented
@SYMTestActions Check that various defect fixes to system panics are correct
@SYMTestExpectedResults Panics respond correctly
*/
case 12:
{
((CTPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-097969-0001"));
_LIT(KPanicTest,"Server panic defect Fix (Pan.4)");
iTest->LogSubTest(KPanicTest);
TestUnInitPanicL(); // DEF097969
}
break;
case 13:
{
/**
@SYMTestCaseID GRAPHICS-WSERV-0501
*/
((CTPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0501"));
_LIT(KPanicTest,"AlphaBlending Bitmap panic defect Fix (Pan.5)");
iTest->LogSubTest(KPanicTest);
TestAlphaBlendingPanicL(); // DEF112916
}
break;
case 14:
{
((CTPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0472"));
_LIT(KPanicTest,"Double construction panic test");
iTest->LogSubTest(KPanicTest);
TestDoubleConstructionL(); // DEF118618
}
break;
case 15:
{
((CTPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0475"));
_LIT(KPanicTest, "RWsSprite Activate() without members panic test");
iTest->LogSubTest(KPanicTest);
TestSpriteActivatePanicL(); //DEF118616
}
break;
/**
@SYMTestCaseID GRAPHICS-WSERV-0497
@SYMDEF DEF133776
@SYMTestCaseDesc Test that a debug only panic occurs when an attempt
is made to cancel a key capture using the wrong cancel capture API.
@SYMTestPriority High
@SYMTestStatus Implemented
@SYMTestActions Check that calling the each RWindowGroup::CancelCapture***() API
using the handle returned from a mismatched RWindowGroup::Capture***() call causes
a debug only panic. Tests each of the three RWindowGroup::CancelCapture***() APIs.
@SYMTestExpectedResults Panics respond correctly in debug only.
*/
case 16:
{
((CTPanicStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0497"));
_LIT(KPanicTest,"TestMismatchedCaptureCancelPanicL");
iTest->LogSubTest(KPanicTest);
TestMismatchedCaptureCancelPanicL();
}
break;
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA
case 17:
{
_LIT(KPanicTest, "Non-Redraw Drawing inside Redrawer Panic Test");
iTest->LogSubTest(KPanicTest);
TestNonRedrawRedrawerL();
}
#endif
default:
((CTPanicStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
((CTPanicStep*)iStep)->CloseTMSGraphicsStep();
TestComplete();
break;
}
((CTPanicStep*)iStep)->RecordTestResultL();
}
#ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA
LOCAL_C TInt DoTestNonRedrawRedrawerL(TInt /* aInt */, TAny * /* aPtr */)
{
CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
CleanupStack::PushL(scheduler);
CActiveScheduler::Install(scheduler);
RWsSession session;
User::LeaveIfError(session.Connect());
CWsScreenDevice *screenDevice = new (ELeave)CWsScreenDevice(session);
User::LeaveIfError(screenDevice->Construct ());
CWindowGc *gc;
User::LeaveIfError(screenDevice->CreateContext(gc));
CNonRedrawWin *nonRedrawWin=CNonRedrawWin::NewL(session, gc);
nonRedrawWin->Invalidate();
CActiveScheduler::Start();
User::After(2000000); // so the Redrawer has a chance to run
CActiveScheduler::Stop();
delete gc;
delete screenDevice;
session.Close();
CleanupStack::PopAndDestroy(scheduler);
return(EWsExitReasonBad);
}
/**
@SYMTestCaseID GRAPHICS-WSERV-0121808
@SYMDEF DEF121808: No more Non-Redraw drawing for NGA (test added during DEF134308)
@SYMTestCaseDesc Test defect fixes to system panics
@SYMTestPriority High
@SYMTestStatus Implemented
@SYMTestActions Check that WServ panics a client which uses Non-Redraw drawing in the Redrawer.
@SYMTestExpectedResults Panics respond correctly
*/
void CTPanic::TestNonRedrawRedrawerL()
{
TEST(iTest->TestWsPanicL(&DoTestNonRedrawRedrawerL,EWservPanicWindowBeginRedrawNotCalled,NULL,NULL));
}
CNonRedrawWin::CRedrawer::CRedrawer(CNonRedrawWin* aWd) :
CActive(CActive::EPriorityStandard), iWd(aWd){
CActiveScheduler::Add(this);
HandleRedrawEvent();
}
CNonRedrawWin::CRedrawer::~CRedrawer(){
Cancel();
}
void CNonRedrawWin::CRedrawer::HandleRedrawEvent(){
iWd->GetSession().RedrawReady(&iStatus);
SetActive();
}
void CNonRedrawWin::CRedrawer::RunL(){
TWsRedrawEvent redrawEvent;
iWd->GetSession().GetRedraw(redrawEvent);
iWd->Redraw();
HandleRedrawEvent();
}
void CNonRedrawWin::CRedrawer::DoCancel(){
iWd->GetSession().RedrawReadyCancel();
}
CNonRedrawWin* CNonRedrawWin::NewL(RWsSession &aSession, CWindowGc *aGc){
CNonRedrawWin* self=new(ELeave)CNonRedrawWin(aSession, aGc);
CleanupStack::PushL(self);
self->ConstrucL();
CleanupStack::Pop(self);
return self;
}
CNonRedrawWin::CNonRedrawWin(RWsSession &aSession, CWindowGc *aGc):
iSession(aSession), iGc(aGc){}
CNonRedrawWin::~CNonRedrawWin(){
delete iRedrawer;
iWd.Close();
iWdGrp.Close();
}
void CNonRedrawWin::Redraw(){
// This is a Non-Redraw Drawing Redrawer; BeginRedraw()/EndRedraw()
// have been intentionally omitted.
iGc->Activate(iWd);
iGc->SetBrushColor(TRgb(255,0,0));
iGc->SetPenColor(KRgbBlue);
iGc->SetPenSize(TSize(10,20));
iGc->DrawRect(TRect(TPoint(10,10),TPoint(50,50)));
iGc->Deactivate();
iSession.Finish();
}
RWsSession &CNonRedrawWin::GetSession(){return iSession;}
void CNonRedrawWin::Invalidate(){iWd.Invalidate();}
void CNonRedrawWin::ConstrucL(){
iWdGrp=RWindowGroup(iSession);
iWdGrp.Construct((TUint32)this,ETrue);
_LIT(KWndGrpName,"NonRedrawWndGrp");
iWdGrp.SetName(KWndGrpName);
iWd=RWindow(iSession);
iWd.Construct(iWdGrp, 0x101);
User::LeaveIfError(iWd.SetExtentErr(TPoint(0,0),TSize(150,150)));
iWd.SetBackgroundColor(KRgbWhite);
iWd.SetOrdinalPosition(0);
iWd.Activate();
iRedrawer=new(ELeave) CRedrawer(this);
}
#endif
TInt RUnInitalisedConnect::Connect(const TDesC &aName, const TVersion &aVersion)
{
return CreateSession(aName, aVersion, 255);
}
TInt RUnInitalisedConnect::Send(const TInt aMsg)
{
return SendReceive(aMsg);
}
__WS_CONSTRUCT_STEP__(Panic)
#pragma warning( disable : 4505 )