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