diff -r 000000000000 -r a41df078684a kerneltest/e32test/dll/t_dllwsd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/dll/t_dllwsd.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,554 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: +* +*/ + + +/** +Overview: + Test DLL Writeable Static Data support + +API Information: + + +Details: + - Each process has independent DLL WSD + - Whether DLL linked directly or indirectly + - Whether DLL loaded dynamically or statically + - DLL WSD is consistent under heavy usage by multiple processes + - IPC works to/from DLL WSD descriptors & TRequestStatus + This source file builds in 4 configurations, with each of + direct and indirect linking either used or not used. + These configurations are set by 4 MM files, t_dllwsd[d][i].mmp + Any of the exe created from the MMP files can be started + to run the tests, it does not matter which is used. + All exe configurations will be used during the tests. + +Platforms/Drives/Compatibility: + All. + +Assumptions/Requirement/Pre-requisites: + + +Failures and causes: + + +Base Port information: + +*/ + +#define __E32TEST_EXTENSION__ + +#include +#include +#include +#include +#include "t_dllwsd_dll.h" +#include "t_dllwsd_dlli.h" + + +LOCAL_D RTest test(_L("T_DLLWSD")); + +enum TTestFunc + { + ETestFuncTestCons=1, + ETestFuncThrash1, + ETestFuncIpcTest, + ETestFuncIpcGet, + ETestFuncIpcReverse, + ETestFuncIpcSet, + ETestFuncPanic, + }; + +// Test session for IPC use of WSD, talks to the same server as RDllWsd +class RIpcTestSession : public RSessionBase + { + public: + TInt Connect() + { + return CreateSession(_L("IpcTestServer"), TVersion()); + } + void Get(TBuf<60000>& buf, TRequestStatus& req) + { + SendReceive(ETestFuncIpcGet, TIpcArgs(&buf), req); + } + void Reverse(TRequestStatus& req) + { + SendReceive(ETestFuncIpcReverse, req); + } + void Set(const TBuf<60000>& buf, TRequestStatus& req) + { + SendReceive(ETestFuncIpcSet, TIpcArgs(&buf), req); + } + }; + +#ifdef T_DLLWSD_DIRECT +void FillBuf(TInt start, TInt inc) + { + for (int ii=0; iiiCount == 0) + CActiveScheduler::Stop(); + } + + void ResetConsistencyCheck() + { + iX=42; + iY=0; + } + + void OptResetConsistencyCheck() + { +#if !defined(T_DLLWSD_DIRECT) && !defined(T_DLLWSD_INDIRECT) + // if DLL has been unloaded (dynamic library closed, no static link) + // WSD will be reset + ResetConsistencyCheck(); +#endif + } + + TInt TestConsistency() + { +#ifdef T_DLLWSD_DIRECT + // static direct + if (WsdFuncX() != iX++) + return KErrGeneral; + if (WsdFuncY() != iY++) + return KErrGeneral; +#endif + +#ifdef T_DLLWSD_INDIRECT + // static indirect + if (IndWsdFuncX() != iX++) + return KErrGeneral; + if (IndWsdFuncY() != iY++) + return KErrGeneral; +#endif + + // dynamic direct + OptResetConsistencyCheck(); + RLibrary lib; + TInt err = lib.Load(_L("t_dllwsd_dll")); + if (err) return err; + if ((*lib.Lookup(1))/*WsdFuncX*/() != iX++) + return KErrGeneral; + if ((*lib.Lookup(2))/*WsdFuncX*/() != iY++) + return KErrGeneral; + lib.Close(); + + // dynamic indirect + OptResetConsistencyCheck(); + err = lib.Load(_L("t_dllwsd_dlli")); + if (err) return err; + if ((*lib.Lookup(1))/*IndWsdFuncX*/() != iX++) + return KErrGeneral; + if ((*lib.Lookup(2))/*IndWsdFuncX*/() != iY++) + return KErrGeneral; + lib.Close(); + + return KErrNone; + } + + TInt Thrash1() + { + TTime start; + start.HomeTime(); + TInt count = 0; + const TTimeIntervalMicroSeconds limit(10000000); // 10 seconds + for (;; count++) + { + TInt err = TestConsistency(); + if (err) return err; + TTime now; + now.HomeTime(); + if (now.MicroSecondsFrom(start) > limit) + break; + } + return count > 0 ? count : -count; + } + + TInt IpcTest() + { +#ifdef T_DLLWSD_DIRECT + RIpcTestSession s; + TInt err = s.Connect(); + if (!err) return err; + WsdBuf().SetLength(WsdBuf().MaxLength()); + for (int i=0; i<10; i++) + { + // 0..n -> buf + FillBuf(0,1); + err = CheckBuf(0,1); + if (!err) return err; + + // buf -> server + s.Set(WsdBuf(), WsdReq()); + err = CheckBuf(0,1); + if (!err) return err; + + // use TReqestStatus in WSD + User::WaitForRequest(WsdReq()); + if (!WsdReq().Int()) return WsdReq().Int(); + + // 0..0 -> buf + FillBuf(0,0); + err = CheckBuf(0,0); + if (!err) return err; + WsdReq() = KRequestPending; + + // reverse buf on server + s.Reverse(WsdReq()); + + // local buf is still 0..0 + err = CheckBuf(0,0); + if (!err) return err; + + // use TReqestStatus in WSD + User::WaitForRequest(WsdReq()); + if (!WsdReq().Int()) return WsdReq().Int(); + + // local buf is still 0..0 + err = CheckBuf(0,0); + if (!err) return err; + + // get buf from server + s.Get(WsdBuf(), WsdReq()); + User::WaitForRequest(WsdReq()); + + // buf is n..0 + err = CheckBuf(59999,-1); + if (!err) return err; + } + s.Close(); + return KErrNone; +#else + return KErrNotSupported; +#endif + } + + void ServiceL(const RMessage2& aMessage) + { +#ifdef T_DLLWSD_DIRECT + TInt ii=0; +#endif + switch (aMessage.Function()) + { + case ETestFuncTestCons: + aMessage.Complete(TestConsistency()); + break; + case ETestFuncThrash1: + aMessage.Complete(Thrash1()); + break; + case ETestFuncIpcTest: + aMessage.Complete(IpcTest()); + break; + case ETestFuncIpcGet: +#ifdef T_DLLWSD_DIRECT + aMessage.WriteL(0, WsdBuf()); + aMessage.Complete(KErrNone); +#else + aMessage.Complete(KErrNotSupported); +#endif + break; + case ETestFuncIpcReverse: +#ifdef T_DLLWSD_DIRECT + for (ii=0; iiStartL(name); + + RProcess::Rendezvous(KErrNone); + CActiveScheduler::Start(); + + delete server; + delete sched; + }); + delete cleanup; + + return err; + } + +// +// Master test controller +// + +class RDllWsd : public RSessionBase + { +public: + RDllWsd(const TDesC& aServerName, const TDesC& aExeName = _L("t_dllwsddi")) + { + test.Start(_L("RDllWsd create")); + RProcess proc; + test_KErrNone(proc.Create(aExeName, aServerName)); + TRequestStatus req; + proc.Rendezvous(req); + proc.Resume(); + User::WaitForRequest(req); + test_KErrNone(req.Int()); + test_KErrNone(CreateSession(aServerName, TVersion())); + proc.Close(); + test.End(); + } + TInt ConsistencyTest() + { + return SendReceive(ETestFuncTestCons); + } + void ThrashTest1(TRequestStatus& aStatus) + { + SendReceive(ETestFuncThrash1, aStatus); + } + TInt IpcTest() + { + return SendReceive(ETestFuncIpcTest); + } + TInt Panic() + { + return SendReceive(ETestFuncPanic); + } + }; + +void BasicTest() + { + test.Start(_L("BasicConsistency")); + + // create a test server/process for each link variant + RDllWsd slaves[] = + { + RDllWsd(_L("slave1"), _L("t_dllwsd")), + RDllWsd(_L("slave2"), _L("t_dllwsdd")), + RDllWsd(_L("slave3"), _L("t_dllwsdi")), + RDllWsd(_L("slave4"), _L("t_dllwsddi")), + RDllWsd(_L("slave5"), _L("t_dllwsd")), + RDllWsd(_L("slave6"), _L("t_dllwsdd")), + RDllWsd(_L("slave7"), _L("t_dllwsdi")), + RDllWsd(_L("slave8"), _L("t_dllwsddi")) + }; + TInt nSlaves = sizeof(slaves)/sizeof(slaves[0]); + TInt ii; + // do this a few times + for (TInt jj=0; jj<10; jj++) + { + // all four test variants + for (ii=0; ii=0; ii--) + slaves[ii].Close(); + + test.End(); + } + +void ThrashTest1() + { + test.Start(_L("ThrashTest1")); + + // create a test server/process for each link variant + RDllWsd slaves[4] = + { + RDllWsd(_L("slaveA"), _L("t_dllwsd")), + RDllWsd(_L("slaveB"), _L("t_dllwsdd")), + RDllWsd(_L("slaveC"), _L("t_dllwsdi")), + RDllWsd(_L("slaveD"), _L("t_dllwsddi")) + }; + + TRequestStatus req[4]; + TInt ii; + // start the thrash tests + for (ii=0; ii<4; ii++) + { + slaves[ii].ThrashTest1(req[ii]); + test.Printf(_L("slave %d thrash started\n"), ii); + } + + // show some progress to indicate that things are running + for (ii=0; ii<8; ii++) + { + test.Printf(_L("Waiting %d\n"), ii); + User::After(1000000); + } + // demonstrate that test processes are still doing their stuff + test.Printf(_L("Still a couple of seconds to wait...\n")); + + // wait till the test process are done + for (ii=0; ii<4; ii++) + { + User::WaitForRequest(req[ii]); + // show how much each process did + test.Printf(_L("Slave %d count = %d\n"), ii, req[ii].Int()); + test_NotNegative(req[ii].Int()); + } + + for (ii=3; ii>=0; ii--) + slaves[ii].Close(); + + test.End(); + } + +void PanicTest() + { + test.Start(_L("PanicTest1")); + + // create a test server/process for each link variant + RDllWsd slaves[4] = + { + RDllWsd(_L("slaveP1"), _L("t_dllwsd")), + RDllWsd(_L("slaveP2"), _L("t_dllwsdd")), + RDllWsd(_L("slaveP3"), _L("t_dllwsdi")), + RDllWsd(_L("slaveP4"), _L("t_dllwsddi")) + }; + TInt ii; + for (ii=0; ii<4; ii++) + slaves[ii].Panic(); + + for (ii=0; ii<4; ii++) + slaves[ii].Close(); + } + +void IpcTest() + { + test.Start(_L("IPC test")); + // these two processes will use t_dllwsddi, static link variant + RDllWsd server(_L("IpcTestServer")); + RDllWsd client(_L("IpcTestClient")); + // client will talk to IpcTestServer, ie the server + test_KErrNone(client.IpcTest()); + client.Close(); + server.Close(); + test.End(); + } + +TInt MasterMain() + { + test.Title(); + test.Start(_L("Test")); + + BasicTest(); + ThrashTest1(); + IpcTest(); +// PanicTest(); + + test.End(); + return KErrNone; + } + +TInt E32Main() + { + if (User::CommandLineLength() > 0) // command line contains server name + return SlaveMain(); + else + return MasterMain(); + } +