kerneltest/e32test/usbho/t_usbdi/src/BaseBulkTestCase.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
child 43 c1f20ce4abcf
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 2008-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:
// @file BaseBulkTestCase.cpp
// @internalComponent
// 
//

#include "BaseBulkTestCase.h"
#include "testpolicy.h"
#include "modelleddevices.h"


 
namespace NUnitTesting_USBDI
	{

//*****************************************************************************************************

//Bulk Timer Class 
CBulkTestTimer* CBulkTestTimer::NewL(MBulkTestTimerObserver& aParent)
	{
	CBulkTestTimer* self = new (ELeave) CBulkTestTimer(aParent);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}


CBulkTestTimer::CBulkTestTimer(MBulkTestTimerObserver& aParent)
:	CTimer(EPriorityStandard),
	iParent(aParent)
	{
	CActiveScheduler::Add(this);
	}


CBulkTestTimer::~CBulkTestTimer()
	{
	}


void CBulkTestTimer::ConstructL()
	{
	LOG_FUNC
	CTimer::ConstructL();
	}


void CBulkTestTimer::RunL()
	{
	LOG_FUNC

	iParent.HandleBulkTestTimerFired();
	}



//*****************************************************************************************************


//Bulk Test Case Base Class
CBaseBulkTestCase::CBaseBulkTestCase(const TDesC& aTestCaseId,TBool aHostFlag, TBool aHostOnly)
	: CBaseTestCase(aTestCaseId, aHostFlag, aHostOnly),
	iInBufferPtr(NULL,0),
	iOutBufferPtr(NULL,0),
	iValidateBufferPtr(NULL,0)	
	{
	
	}


void CBaseBulkTestCase::BaseBulkConstructL()
	{
	iTestDevice = new RUsbDeviceD(this);
	BaseConstructL();
	}


CBaseBulkTestCase::~CBaseBulkTestCase()
	{
	LOG_FUNC
	
	Cancel();

	//Do this before deleting the transfer objects
	//NB this should do nothing if already called from a derived test class
	CloseInterfaceAndPipes();
	
	delete iValidateBuffer;
	delete iInBuffer;
	delete iOutBuffer;

	delete iBulkTestTimer;

	TUint8 count;
	for(count=0;count<KMaxNumOutTransfers;count++)
		{
		delete iOutTransfer[count];
		}
	for(count=0;count<KMaxNumInTransfers;count++)
		{
		delete iInTransfer[count];
		}
	
	delete iControlEp0;
	delete iActorFDF;
	if(!IsHost() && iTestDevice)
		{
		iTestDevice->Close();
		}
	delete iTestDevice;
	}
	
void CBaseBulkTestCase::ExecuteHostTestCaseL()	
	{
	LOG_FUNC
	
	iActorFDF = CActorFDF::NewL(*this);
	iControlEp0 = new (ELeave) CEp0Transfer(iUsbInterface0);
	iActorFDF->Monitor();
	TimeoutIn(30);
	}
	
void CBaseBulkTestCase::HostDoCancel()
	{
	LOG_FUNC
	
	// Cancel the test step timeout timer
	
	CancelTimeout();
	}
	
	
void CBaseBulkTestCase::ExecuteDeviceTestCaseL()
	{
	LOG_FUNC
	
	iTestDevice->OpenL(TestCaseId());
	iTestDevice->SubscribeToReports(iStatus);
	SetActive();
	
	// Connect the device to the host
	
	iTestDevice->SoftwareConnect();
	}
	
void CBaseBulkTestCase::DeviceDoCancel()
	{
	LOG_FUNC
	
	// Cancel the test device error reports
	
	iTestDevice->CancelSubscriptionToReports();
	}
	
	
void CBaseBulkTestCase::DeviceStateChangeL(RUsbDevice::TDeviceState aPreviousState,
				RUsbDevice::TDeviceState aNewState,TInt aCompletionCode)
	{
	LOG_FUNC
	Cancel();
	}
	
	
TInt CBaseBulkTestCase::BaseBulkDeviceInsertedL(TUint aDeviceHandle)
	{
	LOG_FUNC
	RDebug::Printf("this - %08x", this);
	return BaseBulkDeviceInsertedL(aDeviceHandle, EFalse);
	}

void CBaseBulkTestCase::DeviceInsertedL(TUint aDeviceHandle)
	{
	//to be implemnted in individual test cases, possibly with the help of BaseBulkDeviceInsertedL
	BaseBulkDeviceInsertedL(aDeviceHandle);
	};

TInt CBaseBulkTestCase::BaseBulkDeviceInsertedL(TUint aDeviceHandle, TBool aUseTwoInterfaces)
	{
	LOG_FUNC
	TInt err(KErrNone);
	
	// Validate connected device	
	CUsbTestDevice& testDevice = iActorFDF->DeviceL(aDeviceHandle);
	
	RDebug::Printf("device serial number (%S)",&testDevice.SerialNumber());
	RDebug::Printf("Manufacturer (%S)",&testDevice.Manufacturer());
	RDebug::Printf("Product (%S)",&testDevice.Product());
	RDebug::Printf("ProductId (%d)",testDevice.ProductId());
	RDebug::Printf("VendorId (%d)",testDevice.VendorId());
	
	if(testDevice.SerialNumber().Compare(TestCaseId()) != 0)
		{
		// Incorrect device for this test case	

		RDebug::Printf("<Warning %d> Incorrect device serial number (%S) connected for this test case (%S)",
			KErrNotFound,&testDevice.SerialNumber(),&TestCaseId());

		// Start the connection timeout again
		TimeoutIn(30);
		return EDeviceConfigurationError;
		}	


	TUint32 token0;
	err = testDevice.Device().GetTokenForInterface(0,token0);
	if(err != KErrNone)
		{
		RDebug::Printf("<Error %d> Token for interface 0 could not be retrieved",err);

		// Start the connection timeout again
		TimeoutIn(30);
		return EDeviceConfigurationError;
		}
	err = iUsbInterface0.Open(token0); // Default interface setting 0
	if(err != KErrNone)
		{
		RDebug::Printf("<Error %d> Unable to open interface 0 using token %d",err,token0);
		// Start the connection timeout again
		TimeoutIn(30);
		return EDeviceConfigurationError;
		}

	err = SetUpInterfaceAndPipesL(aDeviceHandle, 1);
	if(err != ENone)
		//msg already setup, and failure message sent
		{
		return EDeviceConfigurationError;	
		}
	return ENone;
	}


TInt CBaseBulkTestCase::SetUpInterfaceAndPipesL(TUint aDeviceHandle, TUint8 aInterfaceNum)
	{
	LOG_FUNC
	TInt err(KErrNone);
	TInt endpointAddress;
	RUsbInterface* pTestInterface = NULL;
	RUsbPipe* pTestPipeBulkIn = NULL;
	RUsbPipe* pTestPipeBulkOut1 = NULL;
	RUsbPipe* pTestPipeBulkOut2 = NULL;
	CUsbTestDevice& testDevice = iActorFDF->DeviceL(aDeviceHandle);
	
	switch(aInterfaceNum)
		{
		case 1:
			pTestInterface = &iUsbInterface1;
			pTestPipeBulkIn = &iTestPipeInterface1BulkIn;
			pTestPipeBulkOut1 = &iTestPipeInterface1BulkOut;
			pTestPipeBulkOut2 = NULL;
			break;
		case 2:
			pTestInterface = &iUsbInterface2;
			pTestPipeBulkIn = &iTestPipeInterface2BulkIn;
			pTestPipeBulkOut1 = &iTestPipeInterface2BulkOut1;
			pTestPipeBulkOut2 = &iTestPipeInterface2BulkOut2;
			break;
		default:
			User::Panic(_L("Bulk Interface Number Out Of Range"), KErrArgument);
			break;
		}

	RDebug::Printf("this - %08x", this);
	
	TUint32 token;
	err = testDevice.Device().GetTokenForInterface(aInterfaceNum,token);
	if(err != KErrNone)
		{
		TBuf<256> msg;
		msg.Format(_L("<Error %d> Token for interface 1 could not be retrieved"),err);
		RDebug::Print(msg);
		TTestCaseFailed request(err,msg);
		return EDeviceConfigurationError;
		}
	if(pTestInterface != NULL)
		{
		err = pTestInterface->Open(token); // Default interface setting 1
		if(err != KErrNone)
			{
			TBuf<256> msg;
			msg.Format(_L("<Error %d> Unable to open interface 1 using token %d"),err,token);
			RDebug::Print(msg);
			TTestCaseFailed request(err,msg);
			return EDeviceConfigurationError;
			}
		}
	
	if(pTestPipeBulkIn != NULL)
		{
		err = GetEndpointAddress(*pTestInterface,0,KTransferTypeBulk,KEpDirectionIn,endpointAddress);
		if(err != KErrNone)
			{
			TBuf<256> msg;
			msg.Format(_L("<Error %d> Address for bulk in endpoint could not be obtained"),err);
			RDebug::Print(msg);
			TTestCaseFailed request(err,msg);
			return EDeviceConfigurationError;
			}
		
		RDebug::Printf("IN Endpoint address %08x",endpointAddress);
		
		err = pTestInterface->OpenPipeForEndpoint(*pTestPipeBulkIn,endpointAddress,ETrue);
		if(err != KErrNone)
			{
			TBuf<256> msg;
			msg.Format(_L("<Error %d> Unable to open pipe for endpoint %08x"),err,endpointAddress);
			RDebug::Print(msg);
			TTestCaseFailed request(err,msg);
			return EDeviceConfigurationError;
			}
		}
		
	if(pTestPipeBulkOut1 != NULL)
		{
		err = GetEndpointAddress(*pTestInterface,0,KTransferTypeBulk,KEpDirectionOut,endpointAddress);
		if(err != KErrNone)
			{
			TBuf<256> msg;
			msg.Format(_L("<Error %d> Address for(first) bulk out endpoint could not be obtained"),err);
			RDebug::Print(msg);
			TTestCaseFailed request(err,msg);
			return EDeviceConfigurationError;
			}
		
		RDebug::Printf("OUT Endpoint address %08x",endpointAddress);
		
		err = pTestInterface->OpenPipeForEndpoint(*pTestPipeBulkOut1,endpointAddress,ETrue);
		if(err != KErrNone)
			{
			TBuf<256> msg;
			msg.Format(_L("<Error %d> Unable to open pipe for endpoint %08x"),err,endpointAddress);
			RDebug::Print(msg);
			TTestCaseFailed request(err,msg);
			return EDeviceConfigurationError;
			}
		}
	
	if(pTestPipeBulkOut2 != NULL)
		{
		err = GetEndpointAddress(*pTestInterface,0,KTransferTypeBulk,KEpDirectionOut,1,endpointAddress);
		if(err != KErrNone)
			{
			TBuf<256> msg;
			msg.Format(_L("<Error %d> Address for(second) bulk out endpoint could not be obtained"),err);
			RDebug::Print(msg);
			TTestCaseFailed request(err,msg);
			return EDeviceConfigurationError;
			}
		
		RDebug::Printf("OUT Endpoint address %08x",endpointAddress);
		
		err = pTestInterface->OpenPipeForEndpoint(*pTestPipeBulkOut2,endpointAddress,ETrue);
		if(err != KErrNone)
			{
			TBuf<256> msg;
			msg.Format(_L("<Error %d> Unable to open pipe for endpoint %08x"),err,endpointAddress);
			RDebug::Print(msg);
			TTestCaseFailed request(err,msg);
			return EDeviceConfigurationError;
			}
		}

	return ENone;
	}
	
void CBaseBulkTestCase::CloseInterfaceAndPipes()
	{
	LOG_FUNC
	
	// Close the pipe(s) before interface(s)
	iTestPipeInterface2BulkIn.Close();
	iTestPipeInterface2BulkOut1.Close();
	iTestPipeInterface2BulkOut2.Close();
	iTestPipeInterface1BulkIn.Close();
	iTestPipeInterface1BulkOut.Close();
	
	iUsbInterface2.Close();
	iUsbInterface1.Close();
	iUsbInterface0.Close();
	}

void CBaseBulkTestCase::DeviceRemovedL(TUint aDeviceHandle)
	{
	LOG_FUNC
	
	// The test device should not be removed until the test case has passed
	// so this test case has not completed, and state this event as an error
	
	TestFailed(KErrDisconnected);
	}
	
	
void CBaseBulkTestCase::BusErrorL(TInt aError)
	{
	LOG_FUNC
	
	// This test case handles no failiures on the bus
	
	TestFailed(KErrCompletion);
	}

void CBaseBulkTestCase::HostRunL()
	{
	// Obtain the completion code
	TInt completionCode(iStatus.Int());
	
	if(completionCode == KErrNone)
		{
		// Action timeout
		RDebug::Printf("<Error> Action timeout");
		TestFailed(KErrTimedOut);
		}
	else
		{
		RDebug::Printf("<Error %d> Timeout timer could not complete",completionCode);
		TestFailed(completionCode);
		}
	}

void CBaseBulkTestCase::DeviceRunL()
	{
	LOG_FUNC
	
	// Disconnect the device
	iTestDevice->SoftwareDisconnect();
	
	// Complete the test case request
	TestPolicy().SignalTestComplete(iStatus.Int());
	}

TBool CBaseBulkTestCase::ValidateData (const TDesC8& aDataToValidate, const TDesC8& aDataPattern)
	{
	return ValidateData(aDataToValidate, aDataPattern, aDataPattern.Length());
	}

TBool CBaseBulkTestCase::ValidateData (const TDesC8& aDataToValidate, const TDesC8& aDataPattern, const TUint aNumBytes)
	{
	return ValidateData(aDataToValidate, aDataPattern, 0, aNumBytes);
	}

TBool CBaseBulkTestCase::ValidateData (const TDesC8& aDataToValidate, const TDesC8& aDataPattern, const TUint aStartPoint, const TUint aNumBytes)
	{
	LOG_FUNC
		
	__ASSERT_DEBUG(aDataPattern.Length()!=0, User::Panic(_L("Trying to validate with ZERO LENGTH STRING"), KErrArgument));

	if(aDataToValidate.Length()!=aNumBytes)
		{
		RDebug::Printf("ROUND TRIP VALIDATION: Length Match Failure, Sent = %d, Returned = %d", aNumBytes, aDataToValidate.Length());
		return EFalse;
		}
	TUint startPoint = aStartPoint%aDataPattern.Length();
	TUint numStartBytes = (aDataPattern.Length() - startPoint)%aDataPattern.Length();
	numStartBytes = aNumBytes<numStartBytes?aNumBytes:numStartBytes; //never test for more than aNumBytes
	TUint fullRepeats = (aNumBytes-numStartBytes)/aDataPattern.Length();
	TUint startEndPoint = (fullRepeats*aDataPattern.Length()) + numStartBytes;
	TUint numEndBytes = aNumBytes - startEndPoint;//fullRepeats*aDataPattern.Length() - numStartBytes;
	if(numStartBytes)
		{
		if(aDataToValidate.Left(numStartBytes).Compare(aDataPattern.Mid(startPoint, numStartBytes)) != 0)
			{
			RDebug::Printf("ROUND TRIP VALIDATION: Start Bytes Match Failure");
			RDebug::Printf("ROUND TRIP VALIDATION: numStartBytes = %d", numStartBytes);
			RDebug::Printf("Start of EXPECTED data ...");
			RDebug::RawPrint(aDataPattern.Mid(startPoint, numStartBytes));
			RDebug::Printf("\n");
			RDebug::Printf("Start of RETURNED data ...");				
			RDebug::RawPrint(aDataToValidate.Left(numStartBytes));
			RDebug::Printf("\n");
			return EFalse;
			}
		}
	if(numEndBytes)
		{
		if(aDataToValidate.Mid(startEndPoint,numEndBytes).Compare(aDataPattern.Left(numEndBytes)) != 0)
			{
			RDebug::Printf("ROUND TRIP VALIDATION: End Bytes Match Failure");
			RDebug::Printf("ROUND TRIP VALIDATION: startEndPoint = %d, numEndBytes = %d", startEndPoint, numEndBytes);
			RDebug::Printf("End of EXPECTED data ...");
			RDebug::RawPrint(aDataPattern.Left(numEndBytes));
			RDebug::Printf("\n");
			RDebug::Printf("End of RETURNED data ...");				
			RDebug::RawPrint(aDataToValidate.Mid(startEndPoint,numEndBytes));
			RDebug::Printf("\n");
			return EFalse;
			}
		}
	for(TInt i=0; i<fullRepeats; i++)
		{
		if(aDataToValidate.Mid(numStartBytes + i*aDataPattern.Length(),aDataPattern.Length()).Compare(aDataPattern) != 0)
			{
			RDebug::Printf("ROUND TRIP VALIDATION: Repeated Bytes Match Failure, Repeat %d",i);
			RDebug::Printf("Middle block of EXPECTED data ...");
			RDebug::RawPrint(aDataPattern);
			RDebug::Printf("\n");
			RDebug::Printf("Middle block of RETURNED data ...");
			RDebug::RawPrint(aDataToValidate.Mid(numStartBytes + i*aDataPattern.Length(),aDataPattern.Length()));
			RDebug::Printf("\n");
			return EFalse; //from 'for' loop
			}
		}
	return ETrue;
	}

void CBaseBulkTestCase::RecordTime(const TUint8 aTimerIndex)
	{
	LOG_FUNC
	if(aTimerIndex >= KMaxNumTimers)
		{
		RDebug::Printf("Record Timer with index %d called - index OUT OF RANGE", aTimerIndex);
		User::Panic(_L("BAD TIMER INDEX"), KErrArgument);
		}
	iEndTime[aTimerIndex].HomeTime();
	iTimeElapsed[aTimerIndex] = iEndTime[aTimerIndex].MicroSecondsFrom(iStartTime[aTimerIndex]);
	RDebug::Printf("Timer with index %d completed in %d uSec", aTimerIndex, (TInt)(iTimeElapsed[aTimerIndex].Int64()));
	}

TInt CBaseBulkTestCase::CheckTimes(const TUint8 aFirstTimerIndex, const TUint8 aSecondTimerIndex, const TUint aPercentage)
	{
	LOG_FUNC
	if(aFirstTimerIndex >= KMaxNumTimers)
		{
		RDebug::Printf("First timer with index %d called - index OUT OF RANGE", aFirstTimerIndex);
		User::Panic(_L("BAD TIMER INDEX"), KErrArgument);
		}
	if(aSecondTimerIndex >= KMaxNumTimers)
		{
		RDebug::Printf("Second timer with index %d called - index OUT OF RANGE", aSecondTimerIndex);
		User::Panic(_L("BAD TIMER INDEX"), KErrArgument);
		}

	TInt ret = KErrNone;
	RDebug::Printf("Transfer %d completed in %d uSec\nTransfer %d completed in %d uSec", aFirstTimerIndex, (TInt)(iTimeElapsed[aFirstTimerIndex].Int64()), aSecondTimerIndex, (TInt)(iTimeElapsed[aSecondTimerIndex].Int64()));
	if(aPercentage*iTimeElapsed[aFirstTimerIndex].Int64() > KPercent*iTimeElapsed[aSecondTimerIndex].Int64())
		{
		ret = KErrTooBig;
		RDebug::Printf("Time %d too big", aFirstTimerIndex);
		}
	if(aPercentage*iTimeElapsed[aSecondTimerIndex].Int64() > KPercent*iTimeElapsed[aFirstTimerIndex].Int64())
		{
		ret = KErrTooBig;
		RDebug::Printf("Time %d too big", aSecondTimerIndex);
		}
	
	return ret;
	}

void CBaseBulkTestCase::ResetTimes(const TUint8 aTimerIndex)
	{
	iStartTime[aTimerIndex] = 0;
	iEndTime[aTimerIndex] = 0;
	iTimeElapsed[aTimerIndex] = 0;
	}

TInt CBaseBulkTestCase::CheckAndResetTimes(const TUint8 aFirstTimerIndex, const TUint8 aSecondTimerIndex, const TUint aPercentage)
	{
	LOG_FUNC
	
	TInt ret = CheckTimes(aFirstTimerIndex, aSecondTimerIndex, aPercentage);
	ResetTimes(aFirstTimerIndex);
	ResetTimes(aSecondTimerIndex);
	
	return ret;
	}

void CBaseBulkTestCase::HandleBulkTestTimerFired()
	{
	//do nothing here - leave to derived class if required
	}

	}//end namespace