diff -r 000000000000 -r 08ec8eefde2f loggingservices/eventlogger/test/src/t_logbadclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loggingservices/eventlogger/test/src/t_logbadclient.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,437 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include +#include "LogServShared.h" +#include "logservcli.h" + +/////////////////////////////////////////////////////////////////////////////////////// + +RTest TheTest(_L("t_logbadclient test")); + +const TInt KTestIterCount = 5000; +const TInt KMaxDesArgLen = 1000; +enum TArgType + { + EIntArgType, + ETextArgType, + EBinArgType, + ELastArgType + }; + +const TLogServFunction KLogIpcMsgCodes[] = + { + ELogOperationCancel, ELogOperationGetResult, ELogOperationInitiate, ELogNotify, ELogNotifyCancel, ELogViewCreate, + ELogViewDelete, ELogViewCount, ELogViewOperationInitiate, ELogViewChangeNotificationsRequest, + ELogViewChangeNotificationsCancel, ELogViewFetchChanges, ELogViewNotifyLockStatusChange, + ELogViewNotifyLockStatusChangeCancel, ELogNotifyExtended, ELogNotifyExtendedCancel, ELogNOTUSED + }; + +const TLogOperationType KLogOpTypes[] = + { + ELogOperationEventAdd, ELogOperationEventGet, ELogOperationEventChange, ELogOperationEventDelete, + ELogOperationTypeAdd, ELogOperationTypeGet, ELogOperationTypeChange, ELogOperationTypeDelete, + ELogOperationClearLog, ELogOperationClearRecent, ELogOperationConfigGet, ELogOperationConfigChange, + ELogOperationMaintain, ELogOperationViewSetup, ELogOperationViewRemoveEvent, ELogOperationViewClearDuplicates, + ELogOperationViewSetFlags, ELogOperationViewWindowFetch, (TLogOperationType)-100 + }; + +////////////////////////////////////////////////////////////////////////////////////// + +//If the LogEng server crashes and the test receives KErrServerTerminated error, then the +//next set will contain the last: +// - iteration number; +// - function code; +// - IPC arguments values; +struct TThreadData + { + TInt iIteration; + TInt iFunction; + TArgType iArgType[KMaxMessageArguments]; + TInt iIntArg[KMaxMessageArguments]; + TBuf iTextArg[KMaxMessageArguments]; + TBuf8 iBinArg[KMaxMessageArguments]; + TInt64 iSeed; + }; +////////////////////////////////////////////////////////////////////////////////////// + +_LIT(KPanicCategory, "SrvTerm"); +_LIT(KPanicCategory2, "InvArg"); +const TInt KPanicCode = 1111; +const TInt KPanicCode2 = 2222; + +static TLogClientServerData TheLogIpcData; +static TPtrC8 TheLogIpcDataPtr((const TUint8*)&TheLogIpcData, sizeof(TheLogIpcData)); + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +//Test macros and functions +void Check1(TInt aValue, TInt aLine, TBool aPrintThreadName = EFalse) + { + if(!aValue) + { + if(aPrintThreadName) + { + RThread th; + TName name = th.Name(); + RDebug::Print(_L("*** Thread %S, Line %d\r\n"), &name, aLine); + } + else + { + RDebug::Print(_L("*** Line %d\r\n"), aLine); + } + TheTest(EFalse, aLine); + } + } +void Check2(TInt aValue, TInt aExpected, TInt aLine, TBool aPrintThreadName = EFalse) + { + if(aValue != aExpected) + { + if(aPrintThreadName) + { + RThread th; + TName name = th.Name(); + RDebug::Print(_L("*** Thread %S, Line %d Expected error: %d, got: %d\r\n"), &name, aLine, aExpected, aValue); + } + else + { + RDebug::Print(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue); + } + TheTest(EFalse, aLine); + } + } +#define TEST(arg) ::Check1((arg), __LINE__) +#define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__) +#define TTEST(arg) ::Check1((arg), __LINE__, ETrue) +#define TTEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__, ETrue) + +/////////////////////////////////////////////////////////////////////////////////////// + +void PrintIterationCount(TInt aIteration) + { + if((aIteration % 100) == 0) + { + TTime time; + time.HomeTime(); + TDateTime dt = time.DateTime(); + TBuf<16> tbuf; + tbuf.Format(_L("%02d:%02d:%02d.%06d"), dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond()); + RDebug::Print(_L("-----[%S] Test iterations: %d\r\n"), &tbuf, aIteration); + } + } + +////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// + +//Worker thread function. +//It behaves as a malicious client. Connects to the LogEng server. In each test iteration generates some random values +//for the function number, handle, handle type, IPC arguments. Then sends a command to the server using these +//randomly generated values. If the server crashes and the thread function receives KErrServerTerminated error, +//then the thread kills itself and the main thread will get KPanicCategory and KPanicCode as a reason for the +//worker thread's death. The last set of randomly generated values will be stored in the memory, pointed by aData argument. +TInt ThreadFunc1(void* aData) + { + __UHEAP_MARK; + + CTrapCleanup* tc = CTrapCleanup::New(); + TTEST(tc != NULL); + + TThreadData* p = static_cast (aData); + TTEST(p != NULL); + TThreadData& data = *p; + + RLogSession sess; + TInt err = sess.Connect(); + TTEST2(err, KErrNone); + + while(++data.iIteration <= KTestIterCount) + { + TIpcArgs args; + const TInt KFnCnt = sizeof(KLogIpcMsgCodes) / sizeof(KLogIpcMsgCodes[0]); + TInt fnIdx = Math::Rand(data.iSeed) % KFnCnt; + data.iFunction = KLogIpcMsgCodes[fnIdx]; + PrintIterationCount(data.iIteration); + for(TInt argIdx=0;argIdx 0) + { + data.iArgType[argIdx] = static_cast (Math::Rand(data.iSeed) % ELastArgType); + } + switch(data.iArgType[argIdx]) + { + case EIntArgType: + data.iIntArg[argIdx] = Math::Rand(data.iSeed) % 9711; + args.Set(argIdx, data.iIntArg[argIdx]); + break; + case ETextArgType: + { + TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen; + data.iTextArg[argIdx].SetLength(len); + args.Set(argIdx, &data.iTextArg[argIdx]); + } + break; + case EBinArgType: + { + if(argIdx == 0) + { + //The operations ids are guaranteed to be sequential by logeng.dll implementation. + TheLogIpcData.iOperationId = data.iIteration; + //if(Math::Rand(data.iSeed) & 1) + // { + // TheLogIpcData.iOperationId = 0; + // } + const TInt KTypeCnt = sizeof(KLogOpTypes) / sizeof(KLogOpTypes[0]); + TInt typeIdx = Math::Rand(data.iSeed) % KTypeCnt; + TheLogIpcData.iOperationType = KLogOpTypes[typeIdx]; + TheLogIpcData.iDataSlot1 = Math::Rand(data.iSeed); + TheLogIpcData.iDataSlot2 = Math::Rand(data.iSeed); + args.Set(argIdx, &TheLogIpcDataPtr); + } + else + { + TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen; + data.iBinArg[argIdx].SetLength(len); + args.Set(argIdx, &data.iBinArg[argIdx]); + } + } + break; + default: + User::Panic(KPanicCategory2, KPanicCode2); + break; + } + } + //Send arguments + TRequestStatus stat; + sess.Send(data.iFunction, args, stat); + if(stat.Int() == KErrServerTerminated) + { + User::Panic(KPanicCategory, KPanicCode); + } + else if(stat.Int() == KRequestPending) + { + if(data.iFunction == ELogOperationInitiate) + { + err = sess.Send(ELogOperationGetResult, args); + if(err == KErrServerTerminated) + { + User::Panic(KPanicCategory, KPanicCode); + } + } + else + { + //Give some time to the LogEng server to do something with that async request, then cancel it. + //Otherwise, on a multi-core hardware, the LogEnd server will end up with a long queue of + //pending requests, not cleared if the client side thread is panic'd. It will be a complete chaos. + User::After(20000); + TRequestStatus* s = &stat; + User::RequestComplete(s, KErrCancel); + } + } + } + + sess.Close(); + + delete tc; + + __UHEAP_MARKEND; + + return KErrNone; + } + +/** +@SYMTestCaseID PDS-LOGENG-UT-4045 +@SYMTestCaseDesc In a loop, where the loop iterations are less than KTestIterCount (5000 at the moment), + the test creates a worker thread, which will behave as a malicious client. + If the worker thread crashes the LogEng server, then the worker thread + dies notifying the main thread about the LogEng server crash. The main thread prints the + values used in the last IPC call and crashes the test. +@SYMTestPriority High +@SYMTestActions LogEng, Malicious client simulation test. +@SYMTestExpectedResults Test must not fail +@SYMREQ REQ12746 +*/ +void BadClientTest() + { + TThreadData* p = new TThreadData; + TEST(p != NULL); + TThreadData& data = *p; + data.iFunction = 0; + TTime now; + now.UniversalTime(); + data.iSeed = now.Int64(); + + for(data.iIteration=0;data.iIteration