os/kernelhwsrv/kerneltest/e32test/usbho/t_usbdi/src/BaseTestCase.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // @file basetestcase.cpp
    15 // @internalComponent
    16 // 
    17 //
    18 
    19 #include "BaseTestCase.h"
    20 #include <e32ver.h>
    21 #include <d32usbdi.h>
    22 #include "testdebug.h"
    23 #include "testpolicy.h"
    24 
    25 namespace NUnitTesting_USBDI
    26 	{
    27 	
    28 	
    29 const TUint8 KEpDirectionIn = 0x80;
    30 const TUint8 KEpDirectionOut = 0x00;
    31 const TUint8 KTransferTypeControl = 0x00;
    32 const TUint8 KTransferTypeIsoch = 0x01;
    33 const TUint8 KTransferTypeBulk = 0x02;
    34 const TUint8 KTransferTypeInterrupt = 0x03;	
    35 
    36 const TUint8 KChunkSize  		= 0x80 ; // 128 bytes
    37 const TUint KTreeBufferSize 	= 32*1024 ; // 32k bytes
    38 
    39 _LIT(KRefPath, "Z:\\scripts\\");
    40  _LIT(KGeneratedFilesPath,"C:\\");
    41 _LIT(KExtensionFile,".txt"); 
    42 
    43 
    44 CBaseTestCase::CBaseTestCase(const TDesC& aTestCaseId,TBool aHostFlag, TBool aHostOnly)
    45 :	CActive(EPriorityStandard),
    46 	iHost(aHostFlag),
    47 	iHostOnly(aHostOnly)
    48 	{
    49 	iTestCaseId.Copy(aTestCaseId);
    50 	CActiveScheduler::Add(this);
    51 	}
    52 	
    53 void CBaseTestCase::BaseConstructL()
    54 	{
    55 	LOG_FUNC	
    56 	RDebug::Printf("Creating test case timer");
    57 	TInt err(iTimer.CreateLocal());
    58 	if(err == KErrNone)
    59 		{
    60 		RDebug::Printf("Test case timer created");
    61 		}
    62 	else
    63 		{
    64 		RDebug::Printf("<Error %d> Test case timer could not be created",err);
    65 		User::Leave(err);
    66 		}	
    67 	}
    68 
    69 void CBaseTestCase::TimeoutIn(TInt aTimeoutPeriod)
    70 	{
    71 	LOG_FUNC
    72 	
    73 	CancelTimeout();
    74 	iTimer.After(iStatus,aTimeoutPeriod*1000000);
    75 	SetActive();
    76 	}
    77 
    78 
    79 void CBaseTestCase::CancelTimeout()
    80 	{
    81 	iTimer.Cancel();
    82 	}
    83 
    84 TInt CBaseTestCase::GenerateRefFile(const TDesC& aFileName)
    85 	{
    86 	
    87 	LOG_FUNC
    88 	TBuf<256> refTreeFullFileName(KGeneratedFilesPath);
    89 	refTreeFullFileName.Append(aFileName);	
    90 	refTreeFullFileName.Append(KExtensionFile);
    91 	
    92  	RFile refFile; 
    93 	TInt ret = KErrNone; 
    94 	ret = iFs.Connect();
    95 	if(ret!=KErrNone && ret!=KErrAlreadyExists)
    96 	// if already connected, ignore
    97 		{ 
    98 		RDebug::Printf("iFs.Connect fails, ret = %d", ret);
    99 		return ret;
   100 		}
   101 			
   102 	ret = iFs.Delete(refTreeFullFileName);
   103 	if(ret == KErrNone || ret == KErrNotFound)
   104 		{
   105 		ret = refFile.Create(iFs,refTreeFullFileName,EFileShareAny|EFileWrite);
   106 		}		
   107 	
   108 	if(ret!=KErrNone) 
   109 		{ 
   110 		RDebug::Printf("refFile.Create fails, ret = %d", ret);
   111 		return ret;
   112 		}
   113 		 
   114 	refFile.Write(iTreeBuffer);
   115 	refFile.Flush(); 
   116 	refFile.Close();
   117 			 
   118 	return KErrNone;
   119 	}	
   120 
   121 TInt CBaseTestCase::CompareCurrentTreeToRef(const TDesC& aFileName, TBool& aIsIdentical)
   122 	{
   123 	
   124 	LOG_FUNC								
   125 	TBuf<256> refTreeFullFileName(KRefPath);
   126 	refTreeFullFileName.Append(aFileName);
   127 	refTreeFullFileName.Append(KExtensionFile);	 	
   128 
   129 	TInt ret = KErrNone; 
   130 	ret = iFs.Connect();
   131 	if(ret!=KErrNone && ret!=KErrAlreadyExists)
   132 	// if already connected, ignore
   133 		{ 
   134 		RDebug::Printf("iFs.Connect fails, ret = %d", ret);
   135 		return ret;
   136 		}
   137 
   138 	RFile refFile;
   139 	ret = refFile.Open(iFs,refTreeFullFileName,EFileShareAny|EFileRead);
   140 		
   141 	if(ret!=KErrNone)
   142 		{
   143 		RDebug::Printf("Reference File path: %S", &refTreeFullFileName);
   144 		RDebug::Printf("refFile.Open fails ret = %d", ret);
   145 		return ret;
   146 		}
   147 		
   148 	TInt refFileSize;
   149 	refFile.Size(refFileSize);   
   150 	
   151 	// check size is identical
   152 	if(refFileSize != iTreeBuffer.Size())
   153 		{		
   154 		RDebug::Printf("sizes are NOT identical, refFileSize = %d, iTreeBuffer.Size() = %d ", refFileSize, iTreeBuffer.Size());
   155 		//return KErrGeneral; not an issue, \n encoded differently by perforce... x0D x0A. (x0A only in generated ref file)
   156 		}
   157 		
   158 	// read the file, and put it in a local buffer
   159 	RBuf8 refBuf;
   160 	refBuf.CreateL(refFileSize);
   161 	ret = refFile.Read(0, refBuf, refFileSize);
   162 
   163 	if(ret!=KErrNone)
   164 		{
   165 		RDebug::Printf("refFile.Read fails %d", ret);
   166 		return ret;
   167 		}
   168 		
   169 	// find occurences of \n now 
   170 	RBuf8 copyRefBuf;
   171 	copyRefBuf.CreateL(refFileSize);
   172 	
   173 	for(TInt iRefBuffer=0; iRefBuffer < refFileSize; iRefBuffer++)
   174 		{
   175 		if(refBuf[iRefBuffer] == 0x0D && iRefBuffer != refFileSize-1) // not the last byte
   176 			{			
   177 			if(refBuf[iRefBuffer+1] == 0x0A)
   178 				{				
   179 				copyRefBuf.Append(_L8("\n"));
   180 				continue;
   181 				}			
   182 			}
   183 		// previous is 0x0D, skip... 
   184 		if( refBuf[iRefBuffer] == 0x0A && refBuf[iRefBuffer-1] == 0x0D)
   185 			{
   186 			continue;
   187 			}			
   188 		copyRefBuf.AppendFormat(_L8("%c"), refBuf[iRefBuffer]);				  
   189 		}
   190 	refBuf.Close();
   191 	
   192 	RDebug::Printf("copyRefBuf.Size %d", copyRefBuf.Size());
   193 		
   194 
   195 	// check size is identical, should be identical now
   196 	if(copyRefBuf.Size() != iTreeBuffer.Size())
   197 		{		
   198 		RDebug::Printf("sizes are NOT identical, copyRefBuf.Size() = %d, iTreeBuffer.Size() = %d ", refFileSize, iTreeBuffer.Size());
   199 		return KErrGeneral;
   200 		}
   201 	
   202 	// now compare the 2 buffers		
   203     // Can only go as far as the smallest buffer
   204     TInt bufferSizeToCheck = Min(copyRefBuf.Size(), iTreeBuffer.Size());
   205 	RDebug::Print(_L("bufferSizeToCheck = %d"), bufferSizeToCheck);
   206 
   207 	aIsIdentical = ETrue;	
   208 	for(TInt iRefBuffer=0; iRefBuffer < bufferSizeToCheck; iRefBuffer++)
   209 		{
   210 		if(iTreeBuffer[iRefBuffer] != copyRefBuf[iRefBuffer])
   211 			{
   212 			RDebug::Print(_L("Failed buffer comparison at position %d"), iRefBuffer);
   213             RDebug::Print(_L("Missmatching chars (%d %d) (%c %c)"), iTreeBuffer[iRefBuffer], copyRefBuf[iRefBuffer], iTreeBuffer[iRefBuffer], copyRefBuf[iRefBuffer]);
   214 			aIsIdentical = EFalse;
   215 			break;
   216 			}			 	 	 
   217 		}		
   218 
   219 	RDebug::Print(_L("Finished Buffer comparison aIsIdentical=%d"), aIsIdentical); 
   220 
   221  	copyRefBuf.Close();
   222 	
   223 	return KErrNone;	
   224 	}	
   225 
   226 CBaseTestCase::~CBaseTestCase()
   227 	{
   228 	LOG_FUNC
   229 	Cancel();
   230 	iTimer.Close();
   231 	iTreeBuffer.Close();
   232 	iFs.Close();
   233 	}
   234 
   235 void CBaseTestCase::SelfComplete()
   236 	{
   237 	SelfComplete(KErrNone);
   238 	}
   239 
   240 void CBaseTestCase::SelfComplete(TInt aError)
   241 	{
   242 	TRequestStatus* s = &iStatus;
   243 	iStatus = KRequestPending;
   244 	User::RequestComplete(s,aError);
   245 	SetActive();
   246 	}
   247 
   248 
   249 void CBaseTestCase::DoCancel()
   250 	{
   251 	LOG_FUNC
   252 	iTimer.Cancel();
   253 	if(iHost)
   254 		{
   255 		HostDoCancel();
   256 		}
   257 	else
   258 		{
   259 		DeviceDoCancel();
   260 		}
   261 	}
   262 
   263 void CBaseTestCase::RunL()
   264 	{
   265 	if(iHost)
   266 		{
   267 		HostRunL();
   268 		}
   269 	else
   270 		{
   271 		DeviceRunL();
   272 		}
   273 	}
   274 
   275 TInt CBaseTestCase::RunError(TInt aError)
   276 	{
   277 	LOG_FUNC
   278 	RDebug::Printf("Test case C%lS::RunL left with %d",&iTestCaseId,aError);
   279 	iTestPolicy->SignalTestComplete(aError);
   280 	return KErrNone;
   281 	}
   282 	
   283 TDesC& CBaseTestCase::TestCaseId()
   284 	{
   285 	return iTestCaseId;
   286 	}
   287 	
   288 	
   289 TInt CBaseTestCase::TestResult() const
   290 	{
   291 	return iTestResult;
   292 	}
   293 	
   294 TBool CBaseTestCase::IsHostOnly() const
   295 	{
   296 	return iHostOnly;
   297 	}
   298 		
   299 TBool CBaseTestCase::IsHost() const
   300 	{
   301 	return iHost;
   302 	}
   303 		
   304 void CBaseTestCase::PerformTestL()
   305 	{
   306 	
   307 	if(iHost)
   308 		{
   309 		iTreeBuffer.CreateL(KTreeBufferSize); //32k
   310 		ExecuteHostTestCaseL();
   311 		}
   312 	else
   313 		{
   314 		ExecuteDeviceTestCaseL();
   315 		}	
   316 	}
   317 
   318 void CBaseTestCase::SetTestPolicy(CBasicTestPolicy* aTestPolicy)
   319 	{
   320 	iTestPolicy = aTestPolicy;
   321 	}
   322 
   323 void CBaseTestCase::TestFailed(TInt aFailResult)
   324 	{
   325 	LOG_FUNC
   326 	iTestResult = aFailResult;
   327 	if(!iHostOnly)
   328 		{
   329 		RDebug::Printf("CActiveScheduler::Stop CBaseTestCase::TestFailed");
   330 		CActiveScheduler::Stop();
   331 		}		
   332 	}
   333 	
   334 void CBaseTestCase::TestPassed()
   335 	{
   336 	LOG_FUNC
   337 	iTestResult = KErrNone;	
   338 	if(!iHostOnly)
   339 		{
   340 		RDebug::Printf("CActiveScheduler::Stop CBaseTestCase::TestPassed");
   341 		CActiveScheduler::Stop();
   342 		}
   343 	}
   344 
   345 CBasicTestPolicy& CBaseTestCase::TestPolicy()
   346 	{
   347 	return *iTestPolicy;
   348 	}
   349 	
   350 
   351 /**
   352 Gets the first endpoint address that satisfies the parameters
   353 So caution when there are multiple endpoints on the interface setting
   354 See method below for specifying the endpoint index if more than 
   355 one endpoint of the given type exists on the interface setting
   356 */
   357 TInt CBaseTestCase::GetEndpointAddress(RUsbInterface& aUsbInterface,TInt aInterfaceSetting,
   358 		TUint8 aTransferType,TUint8 aDirection,TInt& aEndpointAddress)
   359 	{
   360 	LOG_FUNC
   361 	
   362 	return GetEndpointAddress(aUsbInterface, aInterfaceSetting, aTransferType, aDirection, 0, aEndpointAddress);
   363 	}
   364 	
   365 /**
   366 Gets the (aIndex+1)th endpoint address that satisfies the parameters
   367 Allows the specification of the endpoint index (starting from ZERO)if more than 
   368 one endpoint of the given type exists on the interface setting
   369 */
   370 TInt CBaseTestCase::GetEndpointAddress(RUsbInterface& aUsbInterface,TInt aInterfaceSetting,
   371 		TUint8 aTransferType,TUint8 aDirection,TUint8 aIndex,TInt& aEndpointAddress)
   372 	{
   373 	LOG_FUNC
   374 		
   375 	// Get the interface descriptor
   376 	RDebug::Printf("Getting the interface descriptor for this alternate setting");
   377 
   378 	TUsbInterfaceDescriptor alternateInterfaceDescriptor;
   379 	TInt err = aUsbInterface.GetAlternateInterfaceDescriptor(aInterfaceSetting, alternateInterfaceDescriptor);
   380 
   381 	if(err)
   382 		{
   383 		RDebug::Printf("<Error %d> Unable to get alternate interface (%d) descriptor",err,aInterfaceSetting);
   384 		return err;
   385 		}
   386 
   387 	// Parse the descriptor tree from the interface 	
   388 	RDebug::Printf("Search the child descriptors for matching endpoint attributes");
   389 	
   390 	TUsbGenericDescriptor* descriptor = alternateInterfaceDescriptor.iFirstChild;
   391 	TUint8 indexCount = 0;
   392 	while(descriptor)
   393 		{
   394 		RDebug::Printf("Check descriptor type for endpoint");
   395 
   396 		// Cast the descriptor to an endpoint descriptor
   397 		TUsbEndpointDescriptor* endpoint = TUsbEndpointDescriptor::Cast(descriptor);
   398 		
   399 		if(endpoint)
   400 			{
   401 			RDebug::Printf("Match attributes for transfer type");
   402 			
   403 			if( (endpoint->Attributes() & aTransferType) == aTransferType)
   404 				{
   405 				RDebug::Printf("Match attributes for endpoint direction");
   406 				
   407 				if( (endpoint->EndpointAddress() & aDirection) == aDirection) 
   408 					{
   409 					if(indexCount==aIndex)
   410 						{
   411 						aEndpointAddress = endpoint->EndpointAddress();
   412 						RDebug::Printf("Endpoint address found");
   413 						return KErrNone;
   414 						}
   415 					else
   416 						{
   417 						indexCount++;
   418 						}
   419 					}
   420 				}
   421 			}
   422 
   423 		descriptor = descriptor->iNextPeer;
   424 		}
   425 
   426 	// Unable to find the endpoint address	
   427 	RDebug::Printf("Unable to find endpoint address matching the specified attributes");
   428 	
   429 	return KErrNotFound;
   430 	}
   431 	
   432 /*static*/ void CBaseTestCase::LogWithCondAndInfo(const TDesC& aCondition, const TDesC& aFileName, TInt aLine)
   433 	{
   434 	TBuf<256> buf;
   435  	buf.Format(KFailText, &aCondition, &aFileName, aLine);
   436  	RDebug::Print(buf); 
   437  	} 	
   438  
   439   	
   440 /*static*/ void CBaseTestCase::PrintAndStoreTree(TUsbGenericDescriptor& aDesc, TInt aDepth)
   441 	{ 
   442 	
   443 	TBuf8<20> buf;	
   444 	for(TInt depth=aDepth;depth>=0;--depth)
   445 		{
   446 		buf.Append(_L8("  "));
   447 		}
   448 		
   449 	//##==TBuf16<40> unicodeBuf;
   450 	TBuf8<40> unicodeBuf;
   451 	unicodeBuf.Copy(buf);	// Ideally this needs conversion to UNICODE
   452 	if(aDesc.iRecognisedAndParsed == TUsbGenericDescriptor::ERecognised)
   453 		{ 
   454 		RDebug::Printf("%S+ length=%d, type=0x%02x", &unicodeBuf, aDesc.ibLength, aDesc.ibDescriptorType);
   455    		iTreeBuffer.AppendFormat(_L8("%S+ length=%d, type=0x%02x\n"), &buf, aDesc.ibLength, aDesc.ibDescriptorType);		
   456 		}
   457 	else
   458 		{
   459 		RDebug::Printf("%S- length=%d, type=0x%02x", &unicodeBuf, aDesc.ibLength, aDesc.ibDescriptorType);
   460 		iTreeBuffer.AppendFormat(_L8("%S- length=%d, type=0x%02x\n"), &buf, aDesc.ibLength, aDesc.ibDescriptorType);
   461 		} 		
   462 
   463 		PrintAndStoreBlob(buf ,aDesc.iBlob);		
   464 		
   465 		if(aDesc.iFirstChild)    
   466 		{
   467 		RDebug::Printf("%S \\ ", &unicodeBuf);
   468 		iTreeBuffer.AppendFormat(_L8("%S \\ \n"), &buf);		
   469 		
   470 		PrintAndStoreTree(*(aDesc.iFirstChild), aDepth+1);		
   471 	
   472 		RDebug::Printf("%S / ", &unicodeBuf);
   473 		iTreeBuffer.AppendFormat(_L8("%S / \n"), &buf);
   474 		}
   475 	if(aDesc.iNextPeer)
   476 		{
   477 		PrintAndStoreTree(*(aDesc.iNextPeer), aDepth);
   478 		}		
   479 	} 
   480 	   
   481 void CBaseTestCase::PrintAndStoreBlob(TDes8& aBuf, TPtrC8& aBlob)
   482 	{
   483 	
   484 	HBufC8* chunk = HBufC8::New(KChunkSize);
   485 	
   486 	TUint nbIter = aBlob.Length()/(KChunkSize/2);
   487 	TUint remainderSize = aBlob.Length()%(KChunkSize/2);
   488 
   489 	if(nbIter == 0)  
   490 		{
   491 		PrintAndStoreChunk(chunk, aBlob.Length() ,aBlob, 0, 0, aBuf );      
   492 		}
   493 	else
   494 		{
   495 		// print chunks
   496 		TUint offset = 0;
   497 		TInt i = 0;
   498 		for(i=0;i<nbIter;++i)
   499 			{
   500 			PrintAndStoreChunk(chunk, (KChunkSize/2) ,aBlob, offset, i, aBuf); 
   501 			offset+=(KChunkSize/2);
   502 			} 
   503 		// remainder
   504 		PrintAndStoreChunk(chunk, remainderSize ,aBlob,offset, i ,aBuf);				
   505 		}
   506 	delete chunk;
   507 	} 
   508 	
   509 void CBaseTestCase::PrintAndStoreChunk(HBufC8* aChunk, TUint aSize, TPtrC8& aBlob, TUint aOffset, TUint aIter, TDes8& aBuf)
   510 	{	
   511 	for(TInt i=0;i<aSize;++i)
   512 		{
   513 		aChunk->Des().AppendFormat(_L8("%02x"), aBlob[i+aOffset]);
   514 		}
   515 		
   516 	TBuf16<40> unicodeBuf;	
   517 	unicodeBuf.Copy(aBuf);
   518 	TBuf16<256> unicodeChunk;	
   519 	unicodeChunk.Copy(aChunk->Des());
   520 			
   521 	if(aIter ==0)
   522 		{		
   523 		RDebug::Printf("%S >%S", &unicodeBuf, &unicodeChunk);					
   524 		iTreeBuffer.AppendFormat(_L8("%S >%S\n"), &aBuf, aChunk);	
   525 		}
   526 	else
   527 		{	
   528 		RDebug::Printf("%S  %S\n", &unicodeBuf, &unicodeChunk); 
   529 		iTreeBuffer.AppendFormat(_L8("%S  %S\n"), &aBuf, aChunk);
   530 		}
   531 	aChunk->Des().Zero();		
   532 	}	
   533 	
   534 TInt CBaseTestCase::CheckTree(TUsbGenericDescriptor& aDevDesc, TUsbGenericDescriptor& aConfigDesc, const TDesC& aFileName)
   535 	{
   536 	LOG_FUNC
   537 	TInt ret = KErrNone;
   538 	
   539 	// flush buffer
   540 	iTreeBuffer.Zero();
   541 	
   542 	// print and store tree from aDevDesc & aConfigDesc
   543 	PrintAndStoreTree(aDevDesc);
   544 	PrintAndStoreTree(aConfigDesc);
   545 	
   546 	// generate file if needed	
   547 	#ifdef GENERATE_TREES
   548 	GenerateRefFile(aFileName);	
   549 	#endif // GENERATE_TREES
   550 	
   551 	// compare tree to ref.
   552 	TBool isIdentical;
   553 	if(KErrNone != CompareCurrentTreeToRef(aFileName, isIdentical))
   554 		{ 
   555 		RDebug::Printf("CompareCurrentTreeToRef error"); 
   556 		ret = KErrGeneral;
   557 		}	
   558 	if(!isIdentical)
   559 		{ 
   560 		RDebug::Printf("!isIdentical"); 
   561 		ret = KErrGeneral;
   562 		}
   563 	return ret;
   564 	}
   565 	
   566 	
   567 TInt CBaseTestCase::ParseConfigDescriptorAndCheckTree(TUsbDeviceDescriptor *devDesc, const TDesC8& configSet, TUint indexTest)
   568 	{
   569 	LOG_FUNC
   570 	// Parse config. descriptor
   571 	TUsbGenericDescriptor* parsed = NULL;
   572 	TInt err = UsbDescriptorParser::Parse(configSet, parsed);
   573 	if(err != KErrNone)
   574 		{
   575 		RDebug::Printf("parsing error : UsbDescriptorParser::Parse"); 
   576 		return err;
   577 		}
   578 	TUsbConfigurationDescriptor* configDesc = TUsbConfigurationDescriptor::Cast(parsed);
   579 	// checks 
   580 	if(configDesc == 0)
   581 		{
   582 		RDebug::Printf("configDesc == 0");
   583 		return KErrGeneral; 
   584 		}
   585 		
   586 	// checking tree 
   587 	TBuf<KMaxName> fname(iTestCaseId);
   588 	fname.AppendFormat(_L("_%d"), indexTest);
   589 	return CheckTree(*devDesc, *configDesc, fname); 
   590 	}	
   591 	
   592 TInt CBaseTestCase::CheckTreeAfterDeviceInsertion(CUsbTestDevice& aTestDevice, const TDesC& aFileName)
   593 	{
   594 	LOG_FUNC
   595 	TUsbGenericDescriptor deviceDesc = aTestDevice.DeviceDescriptor();
   596 	TUsbGenericDescriptor configDesc = aTestDevice.ConfigurationDescriptor();	
   597 	return CheckTree(deviceDesc, configDesc, aFileName); 	
   598 	}	
   599 	
   600 	}