loggingservices/eventlogger/test/src/t_logbadclient.cpp
changeset 0 08ec8eefde2f
child 9 667e88a979d7
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32test.h>
       
    17 #include <bautils.h>
       
    18 #include <e32math.h>
       
    19 #include "LogServShared.h"
       
    20 #include "logservcli.h"
       
    21 
       
    22 ///////////////////////////////////////////////////////////////////////////////////////
       
    23 
       
    24 RTest TheTest(_L("t_logbadclient test"));
       
    25 
       
    26 const TInt KTestIterCount = 5000;
       
    27 const TInt KMaxDesArgLen = 1000;
       
    28 enum TArgType 
       
    29 	{
       
    30 	EIntArgType, 
       
    31 	ETextArgType, 
       
    32 	EBinArgType, 
       
    33 	ELastArgType
       
    34 	};
       
    35 
       
    36 const TLogServFunction KLogIpcMsgCodes[] = 
       
    37 	{
       
    38 	ELogOperationCancel, ELogOperationGetResult, ELogOperationInitiate, ELogNotify, ELogNotifyCancel, ELogViewCreate,
       
    39 	ELogViewDelete, ELogViewCount, ELogViewOperationInitiate, ELogViewChangeNotificationsRequest,
       
    40 	ELogViewChangeNotificationsCancel, ELogViewFetchChanges, ELogViewNotifyLockStatusChange, 
       
    41 	ELogViewNotifyLockStatusChangeCancel, ELogNotifyExtended, ELogNotifyExtendedCancel, ELogNOTUSED   
       
    42 	};
       
    43 
       
    44 const TLogOperationType KLogOpTypes[] =
       
    45 	{
       
    46 	ELogOperationEventAdd, ELogOperationEventGet, ELogOperationEventChange, ELogOperationEventDelete,
       
    47 	ELogOperationTypeAdd, ELogOperationTypeGet, ELogOperationTypeChange, ELogOperationTypeDelete,
       
    48 	ELogOperationClearLog,  ELogOperationClearRecent, ELogOperationConfigGet,  ELogOperationConfigChange,
       
    49 	ELogOperationMaintain, ELogOperationViewSetup, ELogOperationViewRemoveEvent, ELogOperationViewClearDuplicates,
       
    50 	ELogOperationViewSetFlags, ELogOperationViewWindowFetch, (TLogOperationType)-100
       
    51 	};
       
    52 
       
    53 //////////////////////////////////////////////////////////////////////////////////////
       
    54 
       
    55 //If the LogEng server crashes and the test receives KErrServerTerminated error, then the 
       
    56 //next set will contain the last:
       
    57 // - iteration number;
       
    58 // - function code;
       
    59 // - IPC arguments values;
       
    60 struct TThreadData
       
    61 	{
       
    62 	TInt				iIteration;
       
    63 	TInt 				iFunction;
       
    64 	TArgType 			iArgType[KMaxMessageArguments];
       
    65 	TInt 				iIntArg[KMaxMessageArguments];
       
    66 	TBuf<KMaxDesArgLen> iTextArg[KMaxMessageArguments];
       
    67 	TBuf8<KMaxDesArgLen> iBinArg[KMaxMessageArguments];
       
    68 	TInt64 				iSeed;
       
    69 	};
       
    70 //////////////////////////////////////////////////////////////////////////////////////
       
    71 
       
    72 _LIT(KPanicCategory, "SrvTerm");
       
    73 _LIT(KPanicCategory2, "InvArg");
       
    74 const TInt KPanicCode = 1111;
       
    75 const TInt KPanicCode2 = 2222;
       
    76 
       
    77 static TLogClientServerData TheLogIpcData;
       
    78 static TPtrC8 TheLogIpcDataPtr((const TUint8*)&TheLogIpcData, sizeof(TheLogIpcData));
       
    79 
       
    80 ///////////////////////////////////////////////////////////////////////////////////////
       
    81 ///////////////////////////////////////////////////////////////////////////////////////
       
    82 //Test macros and functions
       
    83 void Check1(TInt aValue, TInt aLine, TBool aPrintThreadName = EFalse)
       
    84 	{
       
    85 	if(!aValue)
       
    86 		{
       
    87 		if(aPrintThreadName)
       
    88 			{
       
    89 			RThread th;
       
    90 			TName name = th.Name();
       
    91 			RDebug::Print(_L("*** Thread %S, Line %d\r\n"), &name, aLine);
       
    92 			}
       
    93 		else
       
    94 			{
       
    95 			RDebug::Print(_L("*** Line %d\r\n"), aLine);
       
    96 			}
       
    97 		TheTest(EFalse, aLine);
       
    98 		}
       
    99 	}
       
   100 void Check2(TInt aValue, TInt aExpected, TInt aLine, TBool aPrintThreadName = EFalse)
       
   101 	{
       
   102 	if(aValue != aExpected)
       
   103 		{
       
   104 		if(aPrintThreadName)
       
   105 			{
       
   106 			RThread th;
       
   107 			TName name = th.Name();
       
   108 			RDebug::Print(_L("*** Thread %S, Line %d Expected error: %d, got: %d\r\n"), &name, aLine, aExpected, aValue);
       
   109 			}
       
   110 		else
       
   111 			{
       
   112 			RDebug::Print(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue);
       
   113 			}
       
   114 		TheTest(EFalse, aLine);
       
   115 		}
       
   116 	}
       
   117 #define TEST(arg) ::Check1((arg), __LINE__)
       
   118 #define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__)
       
   119 #define TTEST(arg) ::Check1((arg), __LINE__, ETrue)
       
   120 #define TTEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__, ETrue)
       
   121 
       
   122 ///////////////////////////////////////////////////////////////////////////////////////
       
   123 
       
   124 void PrintIterationCount(TInt aIteration)
       
   125 	{
       
   126 	if((aIteration % 100) == 0)
       
   127 		{
       
   128 		TTime time;
       
   129 		time.HomeTime();
       
   130 		TDateTime dt = time.DateTime();
       
   131 		TBuf<16> tbuf;
       
   132 		tbuf.Format(_L("%02d:%02d:%02d.%06d"), dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond());
       
   133 		RDebug::Print(_L("-----[%S] Test iterations: %d\r\n"), &tbuf, aIteration);
       
   134 		}
       
   135 	}
       
   136 
       
   137 //////////////////////////////////////////////////////////////////////////////////////////////////
       
   138 //////////////////////////////////////////////////////////////////////////////////////////////////
       
   139 
       
   140 //Worker thread function.
       
   141 //It behaves as a malicious client. Connects to the LogEng server. In each test iteration generates some random values
       
   142 //for the function number, handle, handle type, IPC arguments. Then sends a command to the server using these
       
   143 //randomly generated values. If the server crashes and the thread function receives KErrServerTerminated error,
       
   144 //then the thread kills itself and the main thread will get KPanicCategory and KPanicCode as a reason for the
       
   145 //worker thread's death. The last set of randomly generated values will be stored in the memory, pointed by aData argument.
       
   146 TInt ThreadFunc1(void* aData)
       
   147 	{
       
   148 	__UHEAP_MARK;
       
   149 	
       
   150 	CTrapCleanup* tc = CTrapCleanup::New();
       
   151 	TTEST(tc != NULL);
       
   152 
       
   153 	TThreadData* p = static_cast <TThreadData*> (aData);
       
   154 	TTEST(p != NULL);
       
   155 	TThreadData& data = *p;
       
   156 	
       
   157 	RLogSession sess;
       
   158 	TInt err = sess.Connect();
       
   159 	TTEST2(err, KErrNone);
       
   160 
       
   161 	while(++data.iIteration <= KTestIterCount)
       
   162 		{
       
   163 		TIpcArgs args;
       
   164 		const TInt KFnCnt = sizeof(KLogIpcMsgCodes) / sizeof(KLogIpcMsgCodes[0]);
       
   165 		TInt fnIdx = Math::Rand(data.iSeed) % KFnCnt;
       
   166 		data.iFunction = KLogIpcMsgCodes[fnIdx];
       
   167 		PrintIterationCount(data.iIteration);
       
   168 		for(TInt argIdx=0;argIdx<KMaxMessageArguments;++argIdx)
       
   169 			{
       
   170 			//Initialize arguments
       
   171 			data.iArgType[argIdx] = EBinArgType;
       
   172 			if(argIdx > 0)
       
   173 				{
       
   174 				data.iArgType[argIdx] = static_cast <TArgType> (Math::Rand(data.iSeed) % ELastArgType);
       
   175 				}
       
   176 			switch(data.iArgType[argIdx])
       
   177 				{
       
   178 				case EIntArgType:
       
   179 					data.iIntArg[argIdx] = Math::Rand(data.iSeed) % 9711;
       
   180 					args.Set(argIdx, data.iIntArg[argIdx]);
       
   181 					break;
       
   182 				case ETextArgType:
       
   183 					{
       
   184 					TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;	
       
   185 					data.iTextArg[argIdx].SetLength(len);
       
   186 					args.Set(argIdx, &data.iTextArg[argIdx]);
       
   187 					}
       
   188 					break;
       
   189 				case EBinArgType:
       
   190 					{
       
   191 					if(argIdx == 0)
       
   192 						{
       
   193 						//The operations ids are guaranteed to be sequential by logeng.dll implementation.
       
   194 						TheLogIpcData.iOperationId = data.iIteration;
       
   195 						//if(Math::Rand(data.iSeed) & 1)
       
   196 						//	{
       
   197 						//	TheLogIpcData.iOperationId = 0;
       
   198 						//	}
       
   199 						const TInt KTypeCnt = sizeof(KLogOpTypes) / sizeof(KLogOpTypes[0]);
       
   200 						TInt typeIdx = Math::Rand(data.iSeed) % KTypeCnt;
       
   201 						TheLogIpcData.iOperationType = KLogOpTypes[typeIdx];
       
   202 						TheLogIpcData.iDataSlot1 = Math::Rand(data.iSeed);
       
   203 						TheLogIpcData.iDataSlot2 = Math::Rand(data.iSeed);
       
   204 						args.Set(argIdx, &TheLogIpcDataPtr);
       
   205 						}
       
   206 					else
       
   207 						{
       
   208 						TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;	
       
   209 						data.iBinArg[argIdx].SetLength(len);
       
   210 						args.Set(argIdx, &data.iBinArg[argIdx]);
       
   211 						}
       
   212 					}
       
   213 					break;
       
   214 				default:
       
   215 					User::Panic(KPanicCategory2, KPanicCode2);
       
   216 					break;
       
   217 				}
       
   218 			}
       
   219 		//Send arguments
       
   220 		TRequestStatus stat;
       
   221 		sess.Send(data.iFunction, args, stat);
       
   222 		if(stat.Int() == KErrServerTerminated)
       
   223 			{
       
   224 			User::Panic(KPanicCategory, KPanicCode);
       
   225 			}
       
   226 		else if(stat.Int() == KRequestPending)
       
   227 			{
       
   228 			if(data.iFunction == ELogOperationInitiate)
       
   229 				{
       
   230 				err = sess.Send(ELogOperationGetResult, args);
       
   231 				if(err == KErrServerTerminated)
       
   232 					{
       
   233 					User::Panic(KPanicCategory, KPanicCode);
       
   234 					}
       
   235 				}
       
   236 			else
       
   237 				{
       
   238 				//Give some time to the LogEng server to do something with that async request, then cancel it.
       
   239 				//Otherwise, on a multi-core hardware, the LogEnd server will end up with a long queue of
       
   240 				//pending requests, not cleared if the client side thread is panic'd. It will be a complete chaos.
       
   241 				User::After(20000);
       
   242 				TRequestStatus* s = &stat;
       
   243 				User::RequestComplete(s, KErrCancel);
       
   244 				}
       
   245 			}
       
   246 		}
       
   247 
       
   248 	sess.Close();
       
   249 
       
   250 	delete tc;	
       
   251 	
       
   252 	__UHEAP_MARKEND;
       
   253 	
       
   254 	return KErrNone;		
       
   255 	}
       
   256 
       
   257 /**
       
   258 @SYMTestCaseID			PDS-LOGENG-UT-4045
       
   259 @SYMTestCaseDesc		In a loop, where the loop iterations are less than KTestIterCount (5000 at the moment), 
       
   260 						the test creates a worker thread, which will behave as a malicious client. 
       
   261 						If the worker thread crashes the LogEng server, then the worker thread
       
   262 						dies notifying the main thread about the LogEng server crash. The main thread prints the 
       
   263 						values used in the last IPC call and crashes the test.
       
   264 @SYMTestPriority		High
       
   265 @SYMTestActions			LogEng, Malicious client simulation test.
       
   266 @SYMTestExpectedResults Test must not fail
       
   267 @SYMREQ					REQ12746
       
   268 */	
       
   269 void BadClientTest()
       
   270 	{
       
   271 	TThreadData* p = new TThreadData;
       
   272 	TEST(p != NULL);
       
   273 	TThreadData& data = *p;
       
   274 	data.iFunction = 0;
       
   275 	TTime now;
       
   276 	now.UniversalTime();
       
   277 	data.iSeed = now.Int64();
       
   278 
       
   279 	for(data.iIteration=0;data.iIteration<KTestIterCount;++data.iIteration)
       
   280 		{
       
   281 		PrintIterationCount(data.iIteration);
       
   282 		
       
   283 		//Run the malicious client (one test thread which will try to crash the LogEng server)
       
   284 		User::After(200000);
       
   285 		_LIT(KTestThreadName, "TLBCThr");
       
   286 		RThread thread;
       
   287 		TInt err = thread.Create(KTestThreadName, &ThreadFunc1, 0x2000, 0x1000, 0x10000, &data, EOwnerProcess);
       
   288 		if(err == KErrAlreadyExists)
       
   289 			{
       
   290 			TheTest.Printf(_L("##Iteration %d. Function %d. Thread \"%S\" already exists!\r\n"), data.iIteration, data.iFunction, &KTestThreadName);
       
   291 			for(TInt i=0;i<KMaxMessageArguments;++i)
       
   292 				{
       
   293 				RDebug::Print(_L("##Arg %d, Type %d\r\n"), i + 1, data.iArgType[i]);
       
   294 				switch(data.iArgType[i])
       
   295 					{
       
   296 					case EIntArgType:
       
   297 						RDebug::Print(_L("Integer, value=%d\r\n"), data.iIntArg[i]);
       
   298 						break;
       
   299 					case ETextArgType:
       
   300 						RDebug::Print(_L("Text, length=%d\r\n"), data.iTextArg[i].Length());
       
   301 						break;
       
   302 					case EBinArgType:
       
   303 						RDebug::Print(_L("Binary, length=%d\r\n"), data.iBinArg[i].Length());
       
   304 						break;
       
   305 					default:
       
   306 						RDebug::Print(_L("Invalid argument type: %d\r\n"), data.iArgType[i]);
       
   307 						break;
       
   308 					}
       
   309 				}
       
   310 			break;
       
   311 			}
       
   312 		TEST2(err, KErrNone);
       
   313 		User::SetJustInTime(EFalse);		
       
   314 		TRequestStatus status;
       
   315 		thread.Logon(status);
       
   316 		TEST2(status.Int(), KRequestPending);
       
   317 		thread.Resume();
       
   318 		User::WaitForRequest(status);
       
   319 		TExitType exitType = thread.ExitType();
       
   320 		TInt exitReason = thread.ExitReason();
       
   321 		thread.Close();
       
   322 		User::SetJustInTime(ETrue);
       
   323 		
       
   324 		if(exitType == EExitPanic)
       
   325 			{
       
   326 			if(exitReason == KPanicCode)
       
   327 				{
       
   328 				RDebug::Print(_L("##Server terminated!\r\n"));
       
   329 				RDebug::Print(_L("##Iteration=%d, Function=%d\r\n"), data.iIteration, data.iFunction);
       
   330 				for(TInt i=0;i<KMaxMessageArguments;++i)
       
   331 					{
       
   332 					RDebug::Print(_L("##Arg %d, Type %d\r\n"), i + 1, data.iArgType[i]);
       
   333 					switch(data.iArgType[i])
       
   334 						{
       
   335 						case EIntArgType:
       
   336 							RDebug::Print(_L("Integer, value=%d\r\n"), data.iIntArg[i]);
       
   337 							break;
       
   338 						case ETextArgType:
       
   339 							RDebug::Print(_L("Text, length=%d\r\n"), data.iTextArg[i].Length());
       
   340 							break;
       
   341 						case EBinArgType:
       
   342 							RDebug::Print(_L("Binary, length=%d\r\n"), data.iBinArg[i].Length());
       
   343 							break;
       
   344 						default:
       
   345 							RDebug::Print(_L("Invalid argument type: %d\r\n"), data.iArgType[i]);
       
   346 							break;
       
   347 						}
       
   348 					}
       
   349 				TEST(0);
       
   350 				}
       
   351 			}
       
   352 		}//for
       
   353 	delete p;
       
   354 	}
       
   355 
       
   356 /**
       
   357 @SYMTestCaseID			PDS-LOGENG-UT-4044
       
   358 @SYMTestCaseDesc		LogEng server startup - file I/O error simulation test.
       
   359 						The test case shuts down the LogEng server in debug mode.
       
   360 						Then attempts to connect to the server in a file I/O error simulation
       
   361 						loop.
       
   362 @SYMTestPriority		High
       
   363 @SYMTestActions			LogEng server startup - file I/O error simulation test.
       
   364 @SYMTestExpectedResults Test must not fail
       
   365 @SYMREQ					REQ12746
       
   366 */	
       
   367 void LogEngSrvStartupFileIoErrTest()
       
   368 	{
       
   369 	//Shut down the server if it is running
       
   370 	RLogSession sess;
       
   371 	TInt err = sess.Connect();
       
   372 	TEST2(err, KErrNone);
       
   373 
       
   374 	err = sess.Send(ELogMakeTransient, TIpcArgs(1));
       
   375 	TEST2(err, KErrNone);
       
   376 	sess.Close();
       
   377 	
       
   378 	//The shutdown delay is 2 seconds (defined in LogServShutdownTimer.h file). In this csase 5 seconds is more than enough.
       
   379 	User::After(5000000);
       
   380 	
       
   381 	RFs fs;
       
   382 	err = fs.Connect();
       
   383 	TEST2(err, KErrNone);
       
   384 
       
   385 	TBool finished = EFalse;
       
   386 	TInt failCount = 0;
       
   387 
       
   388 	while(!finished)
       
   389 		{
       
   390 		fs.SetErrorCondition(KErrCorrupt, ++failCount);
       
   391 		TInt err = sess.Connect();
       
   392 		fs.SetErrorCondition(KErrNone, 0);
       
   393 		sess.Close();
       
   394 		if(err == KErrNone)
       
   395 			{
       
   396 			finished = ETrue;
       
   397 			}
       
   398 		else
       
   399 			{
       
   400 			TEST2(err, KErrCorrupt);
       
   401 			}
       
   402 		}
       
   403 
       
   404 	fs.Close();
       
   405 	TheTest.Printf(_L("===LogEng Server Startup File I/O error simularion test succeeded at iteration %d\n"), failCount);
       
   406 	}
       
   407 
       
   408 void DoTests()
       
   409 	{
       
   410 	TheTest.Start(_L(" @SYMTestCaseID:PDS-LOGENG-UT-4045: Bad client test"));
       
   411 	BadClientTest();
       
   412 #ifdef _DEBUG	
       
   413 	TheTest.Next(_L(" @SYMTestCaseID:PDS-LOGENG-UT-4044: LogEng Server Startup - File I/O error simulation test"));
       
   414 	LogEngSrvStartupFileIoErrTest();
       
   415 #endif	
       
   416 	}
       
   417 
       
   418 TInt E32Main()
       
   419 	{
       
   420 	TheTest.Title();
       
   421 	
       
   422 	CTrapCleanup* tc = CTrapCleanup::New();
       
   423 	
       
   424 	__UHEAP_MARK;
       
   425 	
       
   426 	DoTests();
       
   427 
       
   428 	__UHEAP_MARKEND;
       
   429 	
       
   430 	TheTest.End();
       
   431 	TheTest.Close();
       
   432 	
       
   433 	delete tc;
       
   434 
       
   435 	User::Heap().Check();
       
   436 	return KErrNone;
       
   437 	}