os/persistentdata/featuremgmt/featuremgr/test/rtest/src/t_fmgrbadclient.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/featuremgmt/featuremgr/test/rtest/src/t_fmgrbadclient.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,452 @@
     1.4 +// Copyright (c) 2009-2010 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 <e32math.h>
    1.21 +#include <featmgr.h>
    1.22 +#include <featureuids.h>
    1.23 +#include "featurepanics.h"
    1.24 +#include <featurecontrol.h>
    1.25 +#include <featurenotifier.h>
    1.26 +#include "../src/inc/featmgrconfiguration.h"
    1.27 +#include "../src/inc/featmgrclientserver.h"
    1.28 +
    1.29 +using namespace NFeature;
    1.30 +
    1.31 +static RTest TheTest(_L("t_fmgrbadclient"));
    1.32 +
    1.33 +const TInt KTestIterCount = 5000;
    1.34 +
    1.35 +enum TArgType 
    1.36 +    {
    1.37 +    EIntArgType, 
    1.38 +    ETextArgType, 
    1.39 +    EBinArgType, 
    1.40 +    ELastArgType
    1.41 +    };
    1.42 +
    1.43 +const TInt KMaxDesArgLen = 1000;
    1.44 +
    1.45 +//If the FeatMgr server crashes and the test receives KErrServerTerminated error, then the 
    1.46 +//next set will contain the last:
    1.47 +// - iteration number;
    1.48 +// - handle type;
    1.49 +// - function code;
    1.50 +// - handle;
    1.51 +// - IPC arguments values;
    1.52 +struct TThreadData
    1.53 +    {
    1.54 +    TInt                iIteration;
    1.55 +    TInt                iFunction;
    1.56 +    TArgType            iArgType[KMaxMessageArguments];
    1.57 +    TInt                iIntArg[KMaxMessageArguments];
    1.58 +    TBuf<KMaxDesArgLen> iTextArg[KMaxMessageArguments];
    1.59 +    TBuf8<KMaxDesArgLen> iBinArg[KMaxMessageArguments];
    1.60 +    TInt64              iSeed;
    1.61 +    };
    1.62 +
    1.63 +_LIT(KPanicCategory, "SrvTerm");
    1.64 +_LIT(KPanicCategory2, "InvArg");
    1.65 +const TInt KPanicCode = 1111;
    1.66 +const TInt KPanicCode2 = 2222;
    1.67 +
    1.68 +///////////////////////////////////////////////////////////////////////////////////////
    1.69 +
    1.70 +//Deletes all created test files.
    1.71 +void DestroyTestEnv()
    1.72 +    {
    1.73 +    }
    1.74 +
    1.75 +///////////////////////////////////////////////////////////////////////////////////////
    1.76 +///////////////////////////////////////////////////////////////////////////////////////
    1.77 +//Test macros and functions
    1.78 +void Check1(TInt aValue, TInt aLine, TBool aPrintThreadName = EFalse)
    1.79 +    {
    1.80 +    if(!aValue)
    1.81 +        {
    1.82 +        DestroyTestEnv();
    1.83 +        if(aPrintThreadName)
    1.84 +            {
    1.85 +            RThread th;
    1.86 +            TName name = th.Name();
    1.87 +            RDebug::Print(_L("*** Expression evaluated to false. Thread %S, Line %d\r\n"), &name, aLine);
    1.88 +            }
    1.89 +        else
    1.90 +            {
    1.91 +            TheTest.Printf(_L("*** Expression evaluated to false. Line %d\r\n"), aLine);
    1.92 +            }
    1.93 +        TheTest(EFalse, aLine);
    1.94 +        }
    1.95 +    }
    1.96 +void Check2(TInt aValue, TInt aExpected, TInt aLine, TBool aPrintThreadName = EFalse)
    1.97 +    {
    1.98 +    if(aValue != aExpected)
    1.99 +        {
   1.100 +        DestroyTestEnv();
   1.101 +        if(aPrintThreadName)
   1.102 +            {
   1.103 +            RThread th;
   1.104 +            TName name = th.Name();
   1.105 +            RDebug::Print(_L("*** Thread %S, Line %d Expected error: %d, got: %d\r\n"), &name, aLine, aExpected, aValue);
   1.106 +            }
   1.107 +        else
   1.108 +            {
   1.109 +            RDebug::Print(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue);
   1.110 +            }
   1.111 +        TheTest(EFalse, aLine);
   1.112 +        }
   1.113 +    }
   1.114 +#define TEST(arg) ::Check1((arg), __LINE__)
   1.115 +#define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__)
   1.116 +#define TTEST(arg) ::Check1((arg), __LINE__, ETrue)
   1.117 +#define TTEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__, ETrue)
   1.118 +
   1.119 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.120 +
   1.121 +static TInt StartFeatMgrServer()
   1.122 +    {
   1.123 +    RProcess server;
   1.124 +    const TUidType serverUid( KNullUid, KServerUid2, KNullUid );
   1.125 +    TInt err = server.Create( KServerExeName, // FeatMgrServer.exe
   1.126 +                           KNullDesC, // A descriptor containing data passed as 
   1.127 +                                      // an argument to the thread function of 
   1.128 +                                      // the new process's main thread, when it 
   1.129 +                                      // is first scheduled.
   1.130 +                           serverUid, // FeatMgr server UID
   1.131 +                           EOwnerProcess ); // Ownership of this process handle 
   1.132 +
   1.133 +    // Return error code if we couldn't create a process
   1.134 +    if ( err == KErrNone )
   1.135 +        {
   1.136 +        // Rendezvous is used to detect server start
   1.137 +        TRequestStatus stat;
   1.138 +        server.Rendezvous( stat );
   1.139 +
   1.140 +        if ( stat != KRequestPending )
   1.141 +            {
   1.142 +            server.Kill( KErrNone ); // Abort startup
   1.143 +            }
   1.144 +        else
   1.145 +            {
   1.146 +            server.Resume();  // Logon OK - start the server
   1.147 +            }
   1.148 +
   1.149 +        User::WaitForRequest( stat ); // Wait for start or death
   1.150 +
   1.151 +        // We can't use the 'exit reason' if the server paniced as this
   1.152 +        // is the panic 'reason' and may be '0' which cannot be distinguished
   1.153 +        // from KErrNone
   1.154 +        err = (server.ExitType() == EExitPanic)? KErrGeneral : stat.Int();
   1.155 +
   1.156 +        // We can close the handle now
   1.157 +        server.Close();        
   1.158 +        }
   1.159 +
   1.160 +    return err;
   1.161 +    }
   1.162 +
   1.163 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.164 +/////////////////////////////        RTestFeatMgrSession          ////////////////////////////////
   1.165 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.166 +
   1.167 +class RTestFeatMgrSession : public RSessionBase
   1.168 +    {
   1.169 +public: 
   1.170 +    TInt Connect();
   1.171 +    void Close();
   1.172 +    TInt SendReceive(TInt aFunction);
   1.173 +    TInt SendReceive(TInt aFunction, const TIpcArgs& aArgs);
   1.174 +    void SendReceive(TInt aFunction, const TIpcArgs& aArgs, TRequestStatus& aStatus);
   1.175 +
   1.176 +private:
   1.177 +    TInt DoCreateSession();
   1.178 +    };
   1.179 +    
   1.180 +TInt RTestFeatMgrSession::Connect()
   1.181 +    {
   1.182 +    TInt err = DoCreateSession();
   1.183 +    if(err != KErrNone && err != KErrAlreadyExists)
   1.184 +        {
   1.185 +        Close();
   1.186 +        }
   1.187 +    return err;
   1.188 +    }
   1.189 +
   1.190 +void RTestFeatMgrSession::Close()
   1.191 +    {
   1.192 +    RSessionBase::Close();
   1.193 +    }
   1.194 +
   1.195 +TInt RTestFeatMgrSession::SendReceive(TInt aFunction)
   1.196 +    {
   1.197 +    return RSessionBase::SendReceive(aFunction);    
   1.198 +    }
   1.199 +    
   1.200 +TInt RTestFeatMgrSession::SendReceive(TInt aFunction, const TIpcArgs& aArgs)
   1.201 +    {
   1.202 +    return RSessionBase::SendReceive(aFunction, aArgs); 
   1.203 +    }
   1.204 +
   1.205 +void RTestFeatMgrSession::SendReceive(TInt aFunction, const TIpcArgs& aArgs, TRequestStatus& aStatus)
   1.206 +    {
   1.207 +    RSessionBase::SendReceive(aFunction, aArgs, aStatus); 
   1.208 +    }
   1.209 +
   1.210 +TInt RTestFeatMgrSession::DoCreateSession()
   1.211 +    {
   1.212 +    const TInt KRetry( 2 );
   1.213 +    // Try this twice
   1.214 +    TInt retry( KRetry );
   1.215 +    TInt err( KErrNone );
   1.216 +
   1.217 +    while ( retry > 0 )
   1.218 +        {
   1.219 +        // Try to create a FeatMgr Server session
   1.220 +        err = CreateSession(KServerProcessName, 
   1.221 +                            TVersion(KServerVersionMajor, KServerVersionMinor, KServerVersionBuild), 
   1.222 +                            KDefaultAsyncSlots);
   1.223 +
   1.224 +        if ( err != KErrNotFound && err != KErrServerTerminated )
   1.225 +            {
   1.226 +            // KErrNone or unrecoverable error
   1.227 +            retry = 0;
   1.228 +            }
   1.229 +        else
   1.230 +            {
   1.231 +            // Return code was KErrNotFound or KErrServerTerminated.
   1.232 +            // Try to start a new FeatMgr Server
   1.233 +            err = StartFeatMgrServer();
   1.234 +
   1.235 +            if ( err != KErrNone && err != KErrAlreadyExists )
   1.236 +                {
   1.237 +                // Unrecoverable error
   1.238 +                retry = 0;
   1.239 +                }
   1.240 +            }
   1.241 +            
   1.242 +        retry--;
   1.243 +        }
   1.244 +            
   1.245 +    return err;
   1.246 +    }
   1.247 +    
   1.248 +void PrintIterationCount(TInt aIteration, TBool aFromThread = EFalse)
   1.249 +    {
   1.250 +    if((aIteration % 100) == 0)
   1.251 +        {
   1.252 +        TTime time;
   1.253 +        time.HomeTime();
   1.254 +        TDateTime dt = time.DateTime();
   1.255 +        TBuf<16> tbuf;
   1.256 +        tbuf.Format(_L("%02d:%02d:%02d.%06d"), dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond());
   1.257 +        if(aFromThread)
   1.258 +            {
   1.259 +            RDebug::Print(_L("-----[%S] Test iterations: %d\r\n"), &tbuf, aIteration);
   1.260 +            }
   1.261 +        else
   1.262 +            {
   1.263 +            TheTest.Printf(_L("-----[%S] Test iterations: %d\r\n"), &tbuf, aIteration);
   1.264 +            }
   1.265 +        }
   1.266 +    }
   1.267 +
   1.268 +//Worker thread function.
   1.269 +//It behaves as a malicious client. Connects to the FeatMgr server. In each test iteration generates some random values
   1.270 +//for the function number, handle, IPC arguments. Then sends a command to the server using these
   1.271 +//randomly generated values. If the server crashes and the thread function receives KErrServerTerminated error,
   1.272 +//then the thread kills itself and the main thread will get KPanicCategory and KPanicCode as a reason for the
   1.273 +//worker thread's death. The last set of randomly generated values will be stored in the memory, pointed by aData argument.
   1.274 +TInt ThreadFunc1(void* aData)
   1.275 +    {
   1.276 +    __UHEAP_MARK;
   1.277 +    
   1.278 +    CTrapCleanup* tc = CTrapCleanup::New();
   1.279 +    TTEST(tc != NULL);
   1.280 +
   1.281 +    TThreadData* p = static_cast <TThreadData*> (aData);
   1.282 +    TTEST(p != NULL);
   1.283 +    TThreadData& data = *p;
   1.284 +
   1.285 +    RTestFeatMgrSession sess;
   1.286 +    TInt err = sess.Connect();
   1.287 +    TTEST2(err, KErrNone);
   1.288 +
   1.289 +    while(++data.iIteration <= KTestIterCount)
   1.290 +        {
   1.291 +        PrintIterationCount(data.iIteration, ETrue);
   1.292 +        TIpcArgs args;
   1.293 +        data.iFunction = Math::Rand(data.iSeed) % (EFeatMgrSWIEnd + 1);//EFeatMgrSWIEnd - the last server message number (without resource checking IPCs))
   1.294 +        for(TInt i=0;i<KMaxMessageArguments;++i)
   1.295 +            {
   1.296 +            //Initialize arguments
   1.297 +            data.iArgType[i] = static_cast <TArgType> (Math::Rand(data.iSeed) % ELastArgType);
   1.298 +            switch(data.iArgType[i])
   1.299 +                {
   1.300 +                case EIntArgType:
   1.301 +                    data.iIntArg[i] = Math::Rand(data.iSeed) % 9711;
   1.302 +                    args.Set(i, data.iIntArg[i]);
   1.303 +                    break;
   1.304 +                case ETextArgType:
   1.305 +                    {
   1.306 +                    TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;  
   1.307 +                    data.iTextArg[i].SetLength(len);
   1.308 +                    args.Set(i, &data.iTextArg[i]);
   1.309 +                    }
   1.310 +                    break;
   1.311 +                case EBinArgType:
   1.312 +                    {
   1.313 +                    TInt len = Math::Rand(data.iSeed) % KMaxDesArgLen;  
   1.314 +                    data.iBinArg[i].SetLength(len);
   1.315 +                    args.Set(i, &data.iBinArg[i]);
   1.316 +                    }
   1.317 +                    break;
   1.318 +                default:
   1.319 +                    User::Panic(KPanicCategory2, KPanicCode2);
   1.320 +                    break;
   1.321 +                }
   1.322 +            }
   1.323 +        //Send arguments
   1.324 +        User::SetJustInTime(EFalse);
   1.325 +        TInt err = KErrNone;
   1.326 +        if(data.iFunction == EFeatMgrReqNotify)
   1.327 +            {
   1.328 +            TRequestStatus status;
   1.329 +            sess.SendReceive(data.iFunction, args, status);
   1.330 +            if(status == KRequestPending)
   1.331 +                {
   1.332 +                err = sess.SendReceive(EFeatMgrReqNotifyCancelAll);
   1.333 +                }
   1.334 +            else
   1.335 +                {
   1.336 +                err = status.Int();
   1.337 +                }
   1.338 +            }
   1.339 +        else
   1.340 +            {
   1.341 +            err = sess.SendReceive(data.iFunction, args);
   1.342 +            }
   1.343 +        if(err == KErrServerTerminated)
   1.344 +            {
   1.345 +            User::Panic(KPanicCategory, KPanicCode);
   1.346 +            }
   1.347 +        User::SetJustInTime(ETrue);
   1.348 +        }
   1.349 +
   1.350 +    sess.Close();
   1.351 +
   1.352 +    delete tc;  
   1.353 +    
   1.354 +    __UHEAP_MARKEND;
   1.355 +    
   1.356 +    return KErrNone;        
   1.357 +    }
   1.358 +
   1.359 +////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.360 +
   1.361 +/**
   1.362 +@SYMTestCaseID          PDS-EFM-CT-4065
   1.363 +@SYMTestCaseDesc        
   1.364 +@SYMTestPriority        High
   1.365 +@SYMTestActions         
   1.366 +@SYMTestExpectedResults Test must not fail
   1.367 +@SYMDEF                 DEF144262
   1.368 +*/
   1.369 +void BadClientTest()
   1.370 +    {
   1.371 +    TThreadData* p = new TThreadData;
   1.372 +    TEST(p != NULL);
   1.373 +    TThreadData& data = *p;
   1.374 +    data.iFunction = 0;
   1.375 +    TTime now;
   1.376 +    now.UniversalTime();
   1.377 +    data.iSeed = now.Int64();
   1.378 +    
   1.379 +    _LIT(KThreadName, "WorkThrd");
   1.380 +    
   1.381 +    for(data.iIteration=0;data.iIteration<KTestIterCount;++data.iIteration)
   1.382 +        {
   1.383 +        PrintIterationCount(data.iIteration);
   1.384 +        //Run the malicious client (one worker theread which will try to crash the FeatMgr server)
   1.385 +        RThread thread;
   1.386 +        TEST2(thread.Create(KThreadName, &ThreadFunc1, 0x2000, 0x1000, 0x10000, &data, EOwnerProcess), KErrNone);
   1.387 +        TRequestStatus status;
   1.388 +        thread.Logon(status);
   1.389 +        TEST2(status.Int(), KRequestPending);
   1.390 +        thread.Resume();
   1.391 +        User::WaitForRequest(status);
   1.392 +        User::SetJustInTime(ETrue); // enable debugger panic handling
   1.393 +        if(thread.ExitType() == EExitPanic)
   1.394 +            {
   1.395 +            if(thread.ExitReason() == KPanicCode)
   1.396 +                {
   1.397 +                TheTest.Printf(_L("##Server terminated!\r\n"));
   1.398 +                TheTest.Printf(_L("##Iteration=%d, Function(hex)=%X, Handle=%d\r\n"), data.iIteration, data.iFunction);
   1.399 +                for(TInt i=0;i<KMaxMessageArguments;++i)
   1.400 +                    {
   1.401 +                    switch(data.iArgType[i])
   1.402 +                        {
   1.403 +                        case EIntArgType:
   1.404 +                            TheTest.Printf(_L("##Arg %d, Integer, value=%d\r\n"), i, data.iIntArg[i]);
   1.405 +                            break;
   1.406 +                        case ETextArgType:
   1.407 +                            TheTest.Printf(_L("##Arg %d, Text,    length=%d\r\n"), i, data.iTextArg[i].Length());
   1.408 +                            break;
   1.409 +                        case EBinArgType:
   1.410 +                            TheTest.Printf(_L("##Arg %d, Binary,  length=%d\r\n"), i, data.iBinArg[i].Length());
   1.411 +                            break;
   1.412 +                        default:
   1.413 +                            TheTest.Printf(_L("##Arg %d, Invalid argument type: %d\r\n"), i, data.iArgType[i]);
   1.414 +                            break;
   1.415 +                        }
   1.416 +                    }
   1.417 +                TEST(0);
   1.418 +                }
   1.419 +            }
   1.420 +        thread.Close();
   1.421 +        }
   1.422 +    User::SetJustInTime(ETrue); // enable debugger panic handling
   1.423 +    delete p;
   1.424 +    }
   1.425 +
   1.426 +void DoTestsL()
   1.427 +    {
   1.428 +    //This test won't pass
   1.429 +    TheTest.Start(_L("@SYMTestCaseID:PDS-EFM-CT-4065 Bad client test"));
   1.430 +    BadClientTest();
   1.431 +    }
   1.432 +
   1.433 +TInt E32Main()
   1.434 +    {
   1.435 +    TheTest.Title();
   1.436 +    
   1.437 +    CTrapCleanup* tc = CTrapCleanup::New();
   1.438 +    TheTest(tc != NULL);
   1.439 +    
   1.440 +    __UHEAP_MARK;
   1.441 +    
   1.442 +    TRAPD(err, DoTestsL());
   1.443 +    DestroyTestEnv();
   1.444 +    TEST2(err, KErrNone);
   1.445 +
   1.446 +    __UHEAP_MARKEND;
   1.447 +    
   1.448 +    TheTest.End();
   1.449 +    TheTest.Close();
   1.450 +    
   1.451 +    delete tc;
   1.452 +
   1.453 +    User::Heap().Check();
   1.454 +    return KErrNone;
   1.455 +    }