diff -r 000000000000 -r dfb7c4ff071f commsfwutils/commsbufs/reference/zerocopy_loopback_driver/test.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsfwutils/commsbufs/reference/zerocopy_loopback_driver/test.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,390 @@ +/* +* 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 "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: +* +*/ +#include +#include + +#include + +#ifdef SYMBIAN_OLD_EXPORT_LOCATION +#include +#else +//this header is not exported, needs to be a user include +#include "zerocopy_loopback_driver.h" +#endif + +#include +#include +#include + +_LIT8(KTestSendData,"abcdefghijklmnopqrstuvwxyz"); +static const TInt KMBuf_MaxAvail = 393216; +static const TInt KMBuf_MBufSize = 128; +static const TInt KMBuf_MBufSizeBig = 1600; +static const TInt KMBuf_InitialAllocation = 128; +static const TInt KMBuf_MinGrowth = 64; +static const TInt KMBuf_GrowthThreshold = 40; + +static const TInt KOneSecond = 1000000; + + +class CZCDriverTestServer : public CTestServer + { +public: + static CZCDriverTestServer* NewL(); + ~CZCDriverTestServer(); + +protected: + const TPtrC ServerName() const; + CTestStep* CreateTestStep(const TDesC& aStepName); + }; + + +_LIT(KZCDriverTestName, "zc_driver_test"); + +class CZCDriverTestStep : public CTestStep + { +public: + + CZCDriverTestStep() + { + SetTestStepName(KZCDriverTestName); + } + +protected: + enum TVerdict doTestStepL(); + + enum TVerdict doTestStepPreambleL() + { + SetTestStepResult(EPass); + return TestStepResult(); + } + }; + +#define TEST_VERDICT(test) if(test) {SetTestStepResult(EFail);} + +enum TVerdict CZCDriverTestStep::doTestStepL() + { + CActiveScheduler* activeScheduler = new(ELeave) CActiveScheduler; + CleanupStack::PushL(activeScheduler); + CActiveScheduler::Install(activeScheduler); + + SetTestStepResult(EFail); + + // Start of testing + INFO_PRINTF1(_L("Load Physical Device")); + TInt r; + r=User::LoadPhysicalDevice(KZeroCopyLoopbackPddFileName); + TEST_VERDICT(r==KErrNone || r==KErrAlreadyExists); + + INFO_PRINTF1(_L("Load Logical Device")); + r=User::LoadLogicalDevice(KZeroCopyLoopbackLddFileName); + TEST_VERDICT(r==KErrNone || r==KErrAlreadyExists); + + // Initialize a commsbuf pond + RCommsBufPondOp commsBufPond; + RArray createInfos; + TCommsBufPoolCreateInfo poolInfoForLargeBufs; + poolInfoForLargeBufs.iBufSize = KMBuf_MBufSizeBig; + poolInfoForLargeBufs.iInitialBufs = KMBuf_InitialAllocation; + poolInfoForLargeBufs.iGrowByBufs = KMBuf_MinGrowth; + poolInfoForLargeBufs.iMinFreeBufs = KMBuf_GrowthThreshold; + poolInfoForLargeBufs.iCeiling = (KMBuf_MaxAvail/2) / KMBuf_MBufSize; + createInfos.AppendL(poolInfoForLargeBufs); + TCommsBufPoolCreateInfo poolInfoForSmallBufs; + poolInfoForSmallBufs.iBufSize = KMBuf_MBufSize; + poolInfoForSmallBufs.iInitialBufs = KMBuf_InitialAllocation; + poolInfoForSmallBufs.iGrowByBufs = KMBuf_MinGrowth; + poolInfoForSmallBufs.iMinFreeBufs = KMBuf_GrowthThreshold; + poolInfoForSmallBufs.iCeiling = (KMBuf_MaxAvail/2) / KMBuf_MBufSize; + createInfos.AppendL(poolInfoForSmallBufs); + User::LeaveIfError(commsBufPond.Open(createInfos)); + createInfos.Close(); + + __KHEAP_MARK; + + INFO_PRINTF1(_L("Open Device")); + RDevice device; + r=device.Open(RZeroCopyLoopbackDriver::Name()); + TEST_VERDICT(r==KErrNone); + + INFO_PRINTF1(_L("Get Device Capabilities")); + RZeroCopyLoopbackDriver::TCaps caps; + TPckgcapsPckg(caps); + capsPckg.FillZ(); // Zero 'caps' so we can tell if GetCaps has really filled it + device.GetCaps(capsPckg); + TVersion expectedVer(RZeroCopyLoopbackDriver::VersionRequired()); + TEST_VERDICT(caps.iVersion.iMajor==expectedVer.iMajor); + TEST_VERDICT(caps.iVersion.iMinor==expectedVer.iMinor); + TEST_VERDICT(caps.iVersion.iBuild==expectedVer.iBuild); + + INFO_PRINTF1(_L("Close Device")); + device.Close(); + + INFO_PRINTF1(_L("Open Logical Channel")); + RZeroCopyLoopbackDriver ldd; + r=ldd.Open(); + TEST_VERDICT(r==KErrNone); + + INFO_PRINTF1(_L("GetConfig")); + RZeroCopyLoopbackDriver::TConfigBuf configBuf; + configBuf.FillZ(); // Zero 'config' so we can tell if GetConfig has really filled it + r=ldd.GetConfig(configBuf); + TEST_VERDICT(r==KErrNone); + + RZeroCopyLoopbackDriver::TConfig& config=configBuf(); + TEST_VERDICT(config.iPddBufferSize!=0); + TEST_VERDICT(config.iMaxSendDataSize!=0); + TEST_VERDICT(config.iMaxReceiveDataSize!=0); + + INFO_PRINTF1(_L("SetConfig")); + TInt speed = configBuf().iSpeed+1; + configBuf().iSpeed = speed; + r=ldd.SetConfig(configBuf); // Use SetConfig to change speed + TEST_VERDICT(r==KErrNone); + + configBuf.FillZ(); + r=ldd.GetConfig(configBuf); + TEST_VERDICT(r==KErrNone); + TEST_VERDICT(configBuf().iSpeed==speed); + TRequestStatus status; + + INFO_PRINTF1(_L("Check access by wrong client")); + RZeroCopyLoopbackDriver ldd2=ldd; + r=ldd2.Duplicate(RThread(),EOwnerProcess); + TEST_VERDICT(r==KErrAccessDenied); + + INFO_PRINTF1(_L("Check handle duplication")); + ldd2=ldd; + r=ldd2.Duplicate(RThread(),EOwnerThread); + TEST_VERDICT(r==KErrNone); + ldd2.Close(); + + INFO_PRINTF1(_L("Load pond")); + r = ldd.LoadPond(commsBufPond); + TEST_VERDICT(r == KErrNone); + + INFO_PRINTF1(_L("Unload pond")); + r = ldd.UnloadPond(); + TEST_VERDICT(r == KErrNone); + + INFO_PRINTF1(_L("Reload pond")); + r = ldd.LoadPond(commsBufPond); + TEST_VERDICT(r == KErrNone); + + INFO_PRINTF1(_L("SendData")); + TCommsBufAllocator allocator = commsBufPond.Allocator(); + RCommsBuf* buf = RCommsBuf::Alloc(KTestSendData().Length(), allocator); + TEST_VERDICT(buf != NULL); + buf->Reset(); + buf->Append(KTestSendData); + ldd.SendData(status, *buf); + User::WaitForRequest(status); + r = status.Int(); + TEST_VERDICT(r == KErrNone); + buf = NULL; + + INFO_PRINTF1(_L("SendData")); + buf = RCommsBuf::Alloc(KTestSendData().Length(), allocator); + TEST_VERDICT(buf != NULL); + buf->Reset(); + buf->Append(KTestSendData); + ldd.SendData(status, *buf); + User::WaitForRequest(status); + r=status.Int(); + TEST_VERDICT(r == KErrNone); + buf = NULL; + + INFO_PRINTF1(_L("ReceiveData")); + RCommsBuf* rxbuf; + ldd.ReceiveData(status); + User::WaitForRequest(status); + r=status.Int(); + TEST_VERDICT(r > 0); + rxbuf = commsBufPond.FromHandle(r); + TEST_VERDICT(rxbuf != 0); + TEST_VERDICT(rxbuf->Length() == KTestSendData().Size()); + TEST_VERDICT(rxbuf->DesC8() == KTestSendData); + TBuf8<256> bufdata; + rxbuf->Read(bufdata); + TEST_VERDICT(bufdata == KTestSendData); + rxbuf->Free(); + rxbuf = NULL; + + INFO_PRINTF1(_L("ReceiveData")); + ldd.ReceiveData(status); + User::WaitForRequest(status); + r=status.Int(); + TEST_VERDICT(r > 0); + rxbuf = commsBufPond.FromHandle(r); + TEST_VERDICT(rxbuf != 0); + TEST_VERDICT(rxbuf->Length() == KTestSendData().Size()); + TEST_VERDICT(rxbuf->DesC8() == KTestSendData); + rxbuf->Read(bufdata); + TEST_VERDICT(bufdata == KTestSendData); + rxbuf->Free(); + rxbuf = NULL; + + INFO_PRINTF1(_L("ReceiveDataCancel")); + ldd.ReceiveData(status); + User::After(KOneSecond); + ldd.ReceiveDataCancel(); + User::WaitForRequest(status); + r=status.Int(); + TEST_VERDICT(r == KErrCancel); + +#if 0 + INFO_PRINTF1(_L("SendDataCancel")); + ldd.SendDataCancel(); + User::WaitForRequest(status); + r=status.Int(); + TEST_VERDICT(r == KErrNone); + buf = NULL; +#endif + + INFO_PRINTF1(_L("Unload pond")); + r = ldd.UnloadPond(); + TEST_VERDICT(r == KErrNone); + + INFO_PRINTF1(_L("Close Logical Channel")); + ldd.Close(); + + __KHEAP_MARKEND; + + INFO_PRINTF1(_L("Unload Logical Device")); + r=User::FreeLogicalDevice(RZeroCopyLoopbackDriver::Name()); + TEST_VERDICT(r==KErrNone); + + INFO_PRINTF1(_L("Unload Physical Device")); + TName pddName(RZeroCopyLoopbackDriver::Name()); + _LIT(KVariantExtension,".template"); + pddName.Append(KVariantExtension); + r=User::FreePhysicalDevice(pddName); + TEST_VERDICT(r==KErrNone); + + // Close the pond + commsBufPond.Close(); + + // End of testing + CleanupStack::PopAndDestroy(activeScheduler); + + SetTestStepResult(EPass); + return TestStepResult(); + } + + +CZCDriverTestServer* CZCDriverTestServer::NewL() +/** + * @return - Instance of the test server + * Same code for Secure and non-secure variants + * Called inside the MainL() function to create and start the + * CTestServer derived server. + */ + { + CZCDriverTestServer* server = new (ELeave) CZCDriverTestServer(); + CleanupStack::PushL(server); + server->StartL(server->ServerName()); + CleanupStack::Pop(server); + return server; + } + + +CZCDriverTestServer::~CZCDriverTestServer() + { + } + + +// Secure variants much simpler +// For EKA2, just an E32Main and a MainL() +LOCAL_C void MainL() +/** + * Secure variant + * Much simpler, uses the new Rendezvous() call to sync with the client + */ + { + // Leave the hooks in for platform security +#if (defined __DATA_CAGING__) + RProcess().DataCaging(RProcess::EDataCagingOn); + RProcess().DataCaging(RProcess::ESecureApiOn); +#endif + CActiveScheduler* sched=NULL; + sched=new(ELeave) CActiveScheduler; + CActiveScheduler::Install(sched); + + CZCDriverTestServer* server = NULL; + + // Create the CTestServer derived server + TRAPD(err,server = CZCDriverTestServer::NewL()); + if(!err) + { + // Sync with the client and enter the active scheduler + RProcess::Rendezvous(KErrNone); + sched->Start(); + } + + delete server; + delete sched; + } + + +GLDEF_C TInt E32Main() +/** + * @return - Standard Epoc error code on process exit + * Secure variant only + * Process entry point. Called by client using RProcess API + */ + { + __UHEAP_MARK; + CTrapCleanup* cleanup = CTrapCleanup::New(); + if(cleanup == NULL) + { + return KErrNoMemory; + } + TRAPD(err,MainL()); + delete cleanup; + __UHEAP_MARKEND; + return err; + } + + +CTestStep* CZCDriverTestServer::CreateTestStep(const TDesC& aStepName) +/** + * @return - A CTestStep derived instance + * Implementation of CTestServer pure virtual + */ + { + CTestStep* testStep = NULL; + if(aStepName.Compare(KZCDriverTestName) == 0) + testStep =new CZCDriverTestStep(); + + return testStep; + } + +const TPtrC CZCDriverTestServer::ServerName() const + { +#if (!defined EKA2) + // On EKA1 our test server is loaded as a dll. + // So we cannot rely on the process name + return KServerName(); +#else + // On EKA2, test server runs in its own process. + // So we arrive at the server name using the exe from which it is loaded. + // This is useful when doing cap tests, as we create duplicate exe's using setcap then. + TParsePtrC serverName(RProcess().FileName()); + return serverName.Name(); +#endif + } +