commsfwutils/commsbufs/reference/zerocopy_loopback_driver/test.cpp
changeset 0 dfb7c4ff071f
--- /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 <test/testexecutestepbase.h>
+#include <test/testexecuteserverbase.h>
+
+#include <e32def_private.h>
+
+#ifdef SYMBIAN_OLD_EXPORT_LOCATION
+#include <comms-infras/zerocopy_loopback_driver.h>
+#else
+//this header is not exported, needs to be a user include
+#include "zerocopy_loopback_driver.h"
+#endif
+
+#include <comms-infras/commsbuf.h>
+#include <comms-infras/commsbufpond.h>
+#include <comms-infras/commsbufpondop.h>
+
+_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<TCommsBufPoolCreateInfo> 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;
+	TPckg<RZeroCopyLoopbackDriver::TCaps>capsPckg(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
+	}
+