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 + }