os/persistentdata/loggingservices/eventlogger/test/src/t_logbadclient.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/loggingservices/eventlogger/test/src/t_logbadclient.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,468 @@
     1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <e32test.h>
    1.20 +#include <bautils.h>
    1.21 +#include <e32math.h>
    1.22 +#include "LogServShared.h"
    1.23 +#include "logservcli.h"
    1.24 +#include "t_logutil.h"
    1.25 +
    1.26 +///////////////////////////////////////////////////////////////////////////////////////
    1.27 +
    1.28 +RTest TheTest(_L("t_logbadclient test"));
    1.29 +
    1.30 +const TInt KTestIterCount = 5000;
    1.31 +const TInt KMaxDesArgLen = 1000;
    1.32 +enum TArgType 
    1.33 +	{
    1.34 +	EIntArgType, 
    1.35 +	ETextArgType, 
    1.36 +	EBinArgType, 
    1.37 +	ELastArgType
    1.38 +	};
    1.39 +
    1.40 +const TLogServFunction KLogIpcMsgCodes[] = 
    1.41 +	{
    1.42 +	ELogOperationCancel, ELogOperationGetResult, ELogOperationInitiate, ELogNotify, ELogNotifyCancel, ELogViewCreate,
    1.43 +	ELogViewDelete, ELogViewCount, ELogViewOperationInitiate, ELogViewChangeNotificationsRequest,
    1.44 +	ELogViewChangeNotificationsCancel, ELogViewFetchChanges, ELogViewNotifyLockStatusChange, 
    1.45 +	ELogViewNotifyLockStatusChangeCancel, ELogNotifyExtended, ELogNotifyExtendedCancel, ELogNOTUSED   
    1.46 +	};
    1.47 +
    1.48 +const TLogOperationType KLogOpTypes[] =
    1.49 +	{
    1.50 +	ELogOperationEventAdd, ELogOperationEventGet, ELogOperationEventChange, ELogOperationEventDelete,
    1.51 +	ELogOperationTypeAdd, ELogOperationTypeGet, ELogOperationTypeChange, ELogOperationTypeDelete,
    1.52 +	ELogOperationClearLog,  ELogOperationClearRecent, ELogOperationConfigGet,  ELogOperationConfigChange,
    1.53 +	ELogOperationMaintain, ELogOperationViewSetup, ELogOperationViewRemoveEvent, ELogOperationViewClearDuplicates,
    1.54 +	ELogOperationViewSetFlags, ELogOperationViewWindowFetch, (TLogOperationType)-100
    1.55 +	};
    1.56 +
    1.57 +//////////////////////////////////////////////////////////////////////////////////////
    1.58 +
    1.59 +//If the LogEng server crashes and the test receives KErrServerTerminated error, then the 
    1.60 +//next set will contain the last:
    1.61 +// - iteration number;
    1.62 +// - function code;
    1.63 +// - IPC arguments values;
    1.64 +struct TThreadData
    1.65 +	{
    1.66 +	TInt				iIteration;
    1.67 +	TInt 				iFunction;
    1.68 +	TArgType 			iArgType[KMaxMessageArguments];
    1.69 +	TInt 				iIntArg[KMaxMessageArguments];
    1.70 +	TBuf<KMaxDesArgLen> iTextArg[KMaxMessageArguments];
    1.71 +	TBuf8<KMaxDesArgLen> iBinArg[KMaxMessageArguments];
    1.72 +	TInt64 				iSeed;
    1.73 +	};
    1.74 +//////////////////////////////////////////////////////////////////////////////////////
    1.75 +
    1.76 +_LIT(KPanicCategory, "SrvTerm");
    1.77 +_LIT(KPanicCategory2, "InvArg");
    1.78 +const TInt KPanicCode = 1111;
    1.79 +const TInt KPanicCode2 = 2222;
    1.80 +
    1.81 +static TLogClientServerData TheLogIpcData;
    1.82 +static TPtrC8 TheLogIpcDataPtr((const TUint8*)&TheLogIpcData, sizeof(TheLogIpcData));
    1.83 +
    1.84 +///////////////////////////////////////////////////////////////////////////////////////
    1.85 +
    1.86 +void PrintIterationCount(TInt aIteration)
    1.87 +	{
    1.88 +	if((aIteration % 100) == 0)
    1.89 +		{
    1.90 +		TTime time;
    1.91 +		time.HomeTime();
    1.92 +		TDateTime dt = time.DateTime();
    1.93 +		TBuf<16> tbuf;
    1.94 +		tbuf.Format(_L("%02d:%02d:%02d.%06d"), dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond());
    1.95 +		TheTest.Printf(_L("-----[%S] Test iterations: %d\r\n"), &tbuf, aIteration);
    1.96 +		}
    1.97 +	}
    1.98 +
    1.99 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.100 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.101 +
   1.102 +//Worker thread function.
   1.103 +//It behaves as a malicious client. Connects to the LogEng server. In each test iteration generates some random values
   1.104 +//for the function number, handle, handle type, IPC arguments. Then sends a command to the server using these
   1.105 +//randomly generated values. If the server crashes and the thread function receives KErrServerTerminated error,
   1.106 +//then the thread kills itself and the main thread will get KPanicCategory and KPanicCode as a reason for the
   1.107 +//worker thread's death. The last set of randomly generated values will be stored in the memory, pointed by aData argument.
   1.108 +TInt ThreadFunc1(void* aData)
   1.109 +	{
   1.110 +	__UHEAP_MARK;
   1.111 +	
   1.112 +	CTrapCleanup* tc = CTrapCleanup::New();
   1.113 +	TTEST(tc != NULL);
   1.114 +
   1.115 +	TThreadData* p = static_cast <TThreadData*> (aData);
   1.116 +	TTEST(p != NULL);
   1.117 +	TThreadData& data = *p;
   1.118 +	
   1.119 +	RLogSession sess;
   1.120 +	TInt err = sess.Connect();
   1.121 +	TTEST2(err, KErrNone);
   1.122 +
   1.123 +	while(++data.iIteration <= KTestIterCount)
   1.124 +		{
   1.125 +		TIpcArgs args;
   1.126 +		const TInt KFnCnt = sizeof(KLogIpcMsgCodes) / sizeof(KLogIpcMsgCodes[0]);
   1.127 +		TInt fnIdx = Math::Rand(data.iSeed) % KFnCnt;
   1.128 +		data.iFunction = KLogIpcMsgCodes[fnIdx];
   1.129 +		PrintIterationCount(data.iIteration);
   1.130 +		for(TInt argIdx=0;argIdx<KMaxMessageArguments;++argIdx)
   1.131 +			{
   1.132 +			//Initialize arguments
   1.133 +			data.iArgType[argIdx] = EBinArgType;
   1.134 +			if(argIdx > 0)
   1.135 +				{
   1.136 +				data.iArgType[argIdx] = static_cast <TArgType> (Math::Rand(data.iSeed) % ELastArgType);
   1.137 +				}
   1.138 +			switch(data.iArgType[argIdx])
   1.139 +				{
   1.140 +				case EIntArgType:
   1.141 +					data.iIntArg[argIdx] = Math::Rand(data.iSeed) % 9711;
   1.142 +					args.Set(argIdx, data.iIntArg[argIdx]);
   1.143 +					break;
   1.144 +				case ETextArgType:
   1.145 +					{
   1.146 +					TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;	
   1.147 +					data.iTextArg[argIdx].SetLength(len);
   1.148 +					args.Set(argIdx, &data.iTextArg[argIdx]);
   1.149 +					}
   1.150 +					break;
   1.151 +				case EBinArgType:
   1.152 +					{
   1.153 +					if(argIdx == 0)
   1.154 +						{
   1.155 +						//The operations ids are guaranteed to be sequential by logeng.dll implementation.
   1.156 +						TheLogIpcData.iOperationId = data.iIteration;
   1.157 +						//if(Math::Rand(data.iSeed) & 1)
   1.158 +						//	{
   1.159 +						//	TheLogIpcData.iOperationId = 0;
   1.160 +						//	}
   1.161 +						const TInt KTypeCnt = sizeof(KLogOpTypes) / sizeof(KLogOpTypes[0]);
   1.162 +						TInt typeIdx = Math::Rand(data.iSeed) % KTypeCnt;
   1.163 +						TheLogIpcData.iOperationType = KLogOpTypes[typeIdx];
   1.164 +						TheLogIpcData.iDataSlot1 = Math::Rand(data.iSeed);
   1.165 +						TheLogIpcData.iDataSlot2 = Math::Rand(data.iSeed);
   1.166 +						args.Set(argIdx, &TheLogIpcDataPtr);
   1.167 +						}
   1.168 +					else
   1.169 +						{
   1.170 +						TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;	
   1.171 +						data.iBinArg[argIdx].SetLength(len);
   1.172 +						args.Set(argIdx, &data.iBinArg[argIdx]);
   1.173 +						}
   1.174 +					}
   1.175 +					break;
   1.176 +				default:
   1.177 +					User::Panic(KPanicCategory2, KPanicCode2);
   1.178 +					break;
   1.179 +				}
   1.180 +			}
   1.181 +		//Send arguments
   1.182 +		//RDebug::Print(_L("##data.iFunction=%d\r\n"), data.iFunction);
   1.183 +		TRequestStatus stat;
   1.184 +		sess.Send(data.iFunction, args, stat);
   1.185 +		if(stat.Int() == KErrServerTerminated)
   1.186 +			{
   1.187 +			User::Panic(KPanicCategory, KPanicCode);
   1.188 +			}
   1.189 +		else if(stat.Int() == KRequestPending)
   1.190 +			{
   1.191 +			if(data.iFunction == ELogOperationInitiate)
   1.192 +				{
   1.193 +				//RDebug::Print(_L("##ELogOperationGetResult\r\n"));
   1.194 +				err = sess.Send(ELogOperationGetResult, args);
   1.195 +				if(err == KErrServerTerminated)
   1.196 +					{
   1.197 +					User::Panic(KPanicCategory, KPanicCode);
   1.198 +					}
   1.199 +				}
   1.200 +			else
   1.201 +				{
   1.202 +				//Give some time to the LogEng server to do something with that async request, then cancel it.
   1.203 +				//Otherwise, on a multi-core hardware, the LogEnd server will end up with a long queue of
   1.204 +				//pending requests, not cleared if the client side thread is panic'd. It will be a complete chaos.
   1.205 +				//RDebug::Print(_L("##data.iFunction=%d, wait and cancel async request\r\n"), data.iFunction);
   1.206 +				User::After(100000);
   1.207 +				TRequestStatus* s = &stat;
   1.208 +				User::RequestComplete(s, KErrCancel);
   1.209 +				}
   1.210 +			//RDebug::Print(_L("##---err=%d\r\n"), err);
   1.211 +			}
   1.212 +		}
   1.213 +
   1.214 +	sess.Close();
   1.215 +
   1.216 +	delete tc;	
   1.217 +	
   1.218 +	__UHEAP_MARKEND;
   1.219 +	
   1.220 +	return KErrNone;		
   1.221 +	}
   1.222 +
   1.223 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.224 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.225 +
   1.226 +//Thread function to detect a crash in the server.
   1.227 +//The server should run for the duration of the test.
   1.228 +// return KErrAbort: If failure to start server
   1.229 +// return KErrServerTerminated: If server process is terminated 
   1.230 +
   1.231 +TInt ServerWatcherFunc(TAny* /*aData*/)
   1.232 +	{
   1.233 +	__UHEAP_MARK;
   1.234 +
   1.235 +	_LIT(KLogEngServerName,"LogServ*");
   1.236 +
   1.237 +	TInt err;
   1.238 +
   1.239 +	// Start the server if not already running
   1.240 +	RLogSession sess;
   1.241 +	err = sess.Connect();
   1.242 +	if (err != KErrNone)
   1.243 +		return KErrAbort;
   1.244 +	sess.Close();
   1.245 +
   1.246 +	TFindProcess findProcess(KLogEngServerName);
   1.247 +	TFullName result;
   1.248 +	if ( findProcess.Next(result) != KErrNone )
   1.249 +		return KErrAbort;
   1.250 +	
   1.251 +	RProcess server;
   1.252 +	if( server.Open(findProcess, EOwnerProcess) != KErrNone)
   1.253 +		return KErrAbort;
   1.254 +
   1.255 +	TRequestStatus status;
   1.256 +	server.Logon(status);	
   1.257 + 	User::WaitForRequest(status);
   1.258 +	
   1.259 +	server.Close();
   1.260 +	
   1.261 +	__UHEAP_MARKEND;
   1.262 +
   1.263 +	return KErrServerTerminated;
   1.264 +	}
   1.265 +
   1.266 +
   1.267 +/**
   1.268 +@SYMTestCaseID			PDS-LOGENG-UT-4045
   1.269 +@SYMTestCaseDesc		In a loop, where the loop iterations are less than KTestIterCount (5000 at the moment), 
   1.270 +						the test creates a worker thread, which will behave as a malicious client. 
   1.271 +						If the worker thread crashes the LogEng server, then the worker thread
   1.272 +						dies notifying the main thread about the LogEng server crash. The main thread prints the 
   1.273 +						values used in the last IPC call and crashes the test.
   1.274 +@SYMTestPriority		High
   1.275 +@SYMTestActions			LogEng, Malicious client simulation test.
   1.276 +@SYMTestExpectedResults Test must not fail
   1.277 +@SYMREQ					REQ12746
   1.278 +*/	
   1.279 +void BadClientTest()
   1.280 +	{
   1.281 +	// Start a thread to watch the server process
   1.282 +	RThread serverWatcher;
   1.283 +	TInt err = serverWatcher.Create(_L("ServerWatcher"), &ServerWatcherFunc, 0x2000, 0x1000, 0x10000, NULL, EOwnerProcess);
   1.284 +	TRequestStatus serverStatus;
   1.285 +	serverWatcher.Logon(serverStatus);
   1.286 +	serverWatcher.Resume();
   1.287 +
   1.288 +	TThreadData* p = new TThreadData;
   1.289 +	TEST(p != NULL);
   1.290 +	TThreadData& data = *p;
   1.291 +	data.iFunction = 0;
   1.292 +	TTime now;
   1.293 +	now.UniversalTime();
   1.294 +	data.iSeed = now.Int64();
   1.295 +
   1.296 +	for(data.iIteration=0;data.iIteration<KTestIterCount;++data.iIteration)
   1.297 +		{
   1.298 +		PrintIterationCount(data.iIteration);
   1.299 +		
   1.300 +		//Run the malicious client (one test thread which will try to crash the LogEng server)
   1.301 +		User::After(200000);
   1.302 +		_LIT(KTestThreadName, "TLBCThr");
   1.303 +		RThread thread;
   1.304 +		err = thread.Create(KTestThreadName, &ThreadFunc1, 0x2000, 0x1000, 0x10000, &data, EOwnerProcess);
   1.305 +		if(err == KErrAlreadyExists)
   1.306 +			{
   1.307 +			TheTest.Printf(_L("##Iteration %d. Function %d. Thread \"%S\" already exists!\r\n"), data.iIteration, data.iFunction, &KTestThreadName);
   1.308 +			for(TInt i=0;i<KMaxMessageArguments;++i)
   1.309 +				{
   1.310 +				TheTest.Printf(_L("##Arg %d, Type %d\r\n"), i + 1, data.iArgType[i]);
   1.311 +				switch(data.iArgType[i])
   1.312 +					{
   1.313 +					case EIntArgType:
   1.314 +					    TheTest.Printf(_L("Integer, value=%d\r\n"), data.iIntArg[i]);
   1.315 +						break;
   1.316 +					case ETextArgType:
   1.317 +					    TheTest.Printf(_L("Text, length=%d\r\n"), data.iTextArg[i].Length());
   1.318 +						break;
   1.319 +					case EBinArgType:
   1.320 +					    TheTest.Printf(_L("Binary, length=%d\r\n"), data.iBinArg[i].Length());
   1.321 +						break;
   1.322 +					default:
   1.323 +					    TheTest.Printf(_L("Invalid argument type: %d\r\n"), data.iArgType[i]);
   1.324 +						break;
   1.325 +					}
   1.326 +				}
   1.327 +			break;
   1.328 +			}
   1.329 +		TEST2(err, KErrNone);
   1.330 +		User::SetJustInTime(EFalse);		
   1.331 +		TRequestStatus status;
   1.332 +		thread.Logon(status);
   1.333 +		TEST2(status.Int(), KRequestPending);
   1.334 +		thread.Resume();
   1.335 +		User::WaitForRequest(status, serverStatus);
   1.336 +
   1.337 +		// If the Server has crashed then we must fail		
   1.338 +		if (serverStatus != KRequestPending) 
   1.339 +			{
   1.340 +			TheTest.Printf(_L("##Iteration=%d, Function=%d, Status=%d, Server Status=%d\r\n"), data.iIteration, data.iFunction, status.Int(), serverStatus.Int());
   1.341 +			}
   1.342 +
   1.343 +		TExitType exitType = thread.ExitType();
   1.344 +		TInt exitReason = thread.ExitReason();
   1.345 +		thread.Close();
   1.346 +		User::SetJustInTime(ETrue);
   1.347 +		
   1.348 +		if(exitType == EExitPanic || serverStatus != KRequestPending)
   1.349 +			{
   1.350 +			if(exitReason == KPanicCode || serverStatus != KRequestPending)
   1.351 +				{
   1.352 +				TheTest.Printf(_L("##Server terminated!\r\n"));
   1.353 +				TheTest.Printf(_L("##Iteration=%d, Function=%d, iOperationType=%d, iDataSlot1=%d, iDataSlot2=%d\r\n"), 
   1.354 +						data.iIteration, data.iFunction,
   1.355 +						TheLogIpcData.iOperationType,
   1.356 +						TheLogIpcData.iDataSlot1,
   1.357 +						TheLogIpcData.iDataSlot2);
   1.358 +				for(TInt i=0;i<KMaxMessageArguments;++i)
   1.359 +					{
   1.360 +					TheTest.Printf(_L("##Arg %d, Type %d\r\n"), i + 1, data.iArgType[i]);
   1.361 +					switch(data.iArgType[i])
   1.362 +						{
   1.363 +						case EIntArgType:
   1.364 +						    TheTest.Printf(_L("Integer, value=%d\r\n"), data.iIntArg[i]);
   1.365 +							break;
   1.366 +						case ETextArgType:
   1.367 +						    TheTest.Printf(_L("Text, length=%d\r\n"), data.iTextArg[i].Length());
   1.368 +							break;
   1.369 +						case EBinArgType:
   1.370 +						    TheTest.Printf(_L("Binary, length=%d\r\n"), data.iBinArg[i].Length());
   1.371 +							break;
   1.372 +						default:
   1.373 +						    TheTest.Printf(_L("Invalid argument type: %d\r\n"), data.iArgType[i]);
   1.374 +							break;
   1.375 +						}
   1.376 +					}
   1.377 +				TEST(0);
   1.378 +				}
   1.379 +			}
   1.380 +		}//for
   1.381 +	delete p;
   1.382 +
   1.383 +	// Check to see if the server crashed and not detected by client
   1.384 +	TEST(serverStatus.Int() == KRequestPending);
   1.385 +	serverWatcher.Kill(KErrCancel);
   1.386 +	serverWatcher.Close();
   1.387 +		
   1.388 +	}
   1.389 +
   1.390 +/**
   1.391 +@SYMTestCaseID			PDS-LOGENG-UT-4044
   1.392 +@SYMTestCaseDesc		LogEng server startup - file I/O error simulation test.
   1.393 +						The test case shuts down the LogEng server in debug mode.
   1.394 +						Then attempts to connect to the server in a file I/O error simulation
   1.395 +						loop.
   1.396 +@SYMTestPriority		High
   1.397 +@SYMTestActions			LogEng server startup - file I/O error simulation test.
   1.398 +@SYMTestExpectedResults Test must not fail
   1.399 +@SYMREQ					REQ12746
   1.400 +*/	
   1.401 +void LogEngSrvStartupFileIoErrTest()
   1.402 +	{
   1.403 +	//Shut down the server if it is running
   1.404 +	RLogSession sess;
   1.405 +	TInt err = sess.Connect();
   1.406 +	TEST2(err, KErrNone);
   1.407 +
   1.408 +	err = sess.Send(ELogMakeTransient, TIpcArgs(1));
   1.409 +	TEST2(err, KErrNone);
   1.410 +	sess.Close();
   1.411 +	
   1.412 +	//The shutdown delay is 2 seconds (defined in LogServShutdownTimer.h file). In this csase 5 seconds is more than enough.
   1.413 +	User::After(5000000);
   1.414 +	
   1.415 +	RFs fs;
   1.416 +	err = fs.Connect();
   1.417 +	TEST2(err, KErrNone);
   1.418 +
   1.419 +	TBool finished = EFalse;
   1.420 +	TInt failCount = 0;
   1.421 +
   1.422 +	while(!finished)
   1.423 +		{
   1.424 +		fs.SetErrorCondition(KErrCorrupt, ++failCount);
   1.425 +		TInt err = sess.Connect();
   1.426 +		fs.SetErrorCondition(KErrNone, 0);
   1.427 +		sess.Close();
   1.428 +		if(err == KErrNone)
   1.429 +			{
   1.430 +			finished = ETrue;
   1.431 +			}
   1.432 +		else
   1.433 +			{
   1.434 +			TEST2(err, KErrCorrupt);
   1.435 +			}
   1.436 +		}
   1.437 +
   1.438 +	fs.Close();
   1.439 +	TheTest.Printf(_L("===LogEng Server Startup File I/O error simularion test succeeded at iteration %d\n"), failCount);
   1.440 +	}
   1.441 +
   1.442 +void DoTests()
   1.443 +	{
   1.444 +	TheTest.Start(_L(" @SYMTestCaseID:PDS-LOGENG-UT-4045: Bad client test"));
   1.445 +	BadClientTest();
   1.446 +#ifdef _DEBUG	
   1.447 +	TheTest.Next(_L(" @SYMTestCaseID:PDS-LOGENG-UT-4044: LogEng Server Startup - File I/O error simulation test"));
   1.448 +	LogEngSrvStartupFileIoErrTest();
   1.449 +#endif	
   1.450 +	}
   1.451 +
   1.452 +TInt E32Main()
   1.453 +	{
   1.454 +	TheTest.Title();
   1.455 +	
   1.456 +	CTrapCleanup* tc = CTrapCleanup::New();
   1.457 +	
   1.458 +	__UHEAP_MARK;
   1.459 +	
   1.460 +	DoTests();
   1.461 +
   1.462 +	__UHEAP_MARKEND;
   1.463 +	
   1.464 +	TheTest.End();
   1.465 +	TheTest.Close();
   1.466 +	
   1.467 +	delete tc;
   1.468 +
   1.469 +	User::Heap().Check();
   1.470 +	return KErrNone;
   1.471 +	}