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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // @file basetestcase.cpp
19 #include "BaseTestCase.h"
22 #include "testdebug.h"
23 #include "testpolicy.h"
25 namespace NUnitTesting_USBDI
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;
36 const TUint8 KChunkSize = 0x80 ; // 128 bytes
37 const TUint KTreeBufferSize = 32*1024 ; // 32k bytes
39 _LIT(KRefPath, "Z:\\scripts\\");
40 _LIT(KGeneratedFilesPath,"C:\\");
41 _LIT(KExtensionFile,".txt");
44 CBaseTestCase::CBaseTestCase(const TDesC& aTestCaseId,TBool aHostFlag, TBool aHostOnly)
45 : CActive(EPriorityStandard),
49 iTestCaseId.Copy(aTestCaseId);
50 CActiveScheduler::Add(this);
53 void CBaseTestCase::BaseConstructL()
56 RDebug::Printf("Creating test case timer");
57 TInt err(iTimer.CreateLocal());
60 RDebug::Printf("Test case timer created");
64 RDebug::Printf("<Error %d> Test case timer could not be created",err);
69 void CBaseTestCase::TimeoutIn(TInt aTimeoutPeriod)
74 iTimer.After(iStatus,aTimeoutPeriod*1000000);
79 void CBaseTestCase::CancelTimeout()
84 TInt CBaseTestCase::GenerateRefFile(const TDesC& aFileName)
88 TBuf<256> refTreeFullFileName(KGeneratedFilesPath);
89 refTreeFullFileName.Append(aFileName);
90 refTreeFullFileName.Append(KExtensionFile);
95 if(ret!=KErrNone && ret!=KErrAlreadyExists)
96 // if already connected, ignore
98 RDebug::Printf("iFs.Connect fails, ret = %d", ret);
102 ret = iFs.Delete(refTreeFullFileName);
103 if(ret == KErrNone || ret == KErrNotFound)
105 ret = refFile.Create(iFs,refTreeFullFileName,EFileShareAny|EFileWrite);
110 RDebug::Printf("refFile.Create fails, ret = %d", ret);
114 refFile.Write(iTreeBuffer);
121 TInt CBaseTestCase::CompareCurrentTreeToRef(const TDesC& aFileName, TBool& aIsIdentical)
125 TBuf<256> refTreeFullFileName(KRefPath);
126 refTreeFullFileName.Append(aFileName);
127 refTreeFullFileName.Append(KExtensionFile);
131 if(ret!=KErrNone && ret!=KErrAlreadyExists)
132 // if already connected, ignore
134 RDebug::Printf("iFs.Connect fails, ret = %d", ret);
139 ret = refFile.Open(iFs,refTreeFullFileName,EFileShareAny|EFileRead);
143 RDebug::Printf("Reference File path: %S", &refTreeFullFileName);
144 RDebug::Printf("refFile.Open fails ret = %d", ret);
149 refFile.Size(refFileSize);
151 // check size is identical
152 if(refFileSize != iTreeBuffer.Size())
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)
158 // read the file, and put it in a local buffer
160 refBuf.CreateL(refFileSize);
161 ret = refFile.Read(0, refBuf, refFileSize);
165 RDebug::Printf("refFile.Read fails %d", ret);
169 // find occurences of \n now
171 copyRefBuf.CreateL(refFileSize);
173 for(TInt iRefBuffer=0; iRefBuffer < refFileSize; iRefBuffer++)
175 if(refBuf[iRefBuffer] == 0x0D && iRefBuffer != refFileSize-1) // not the last byte
177 if(refBuf[iRefBuffer+1] == 0x0A)
179 copyRefBuf.Append(_L8("\n"));
183 // previous is 0x0D, skip...
184 if( refBuf[iRefBuffer] == 0x0A && refBuf[iRefBuffer-1] == 0x0D)
188 copyRefBuf.AppendFormat(_L8("%c"), refBuf[iRefBuffer]);
192 RDebug::Printf("copyRefBuf.Size %d", copyRefBuf.Size());
195 // check size is identical, should be identical now
196 if(copyRefBuf.Size() != iTreeBuffer.Size())
198 RDebug::Printf("sizes are NOT identical, copyRefBuf.Size() = %d, iTreeBuffer.Size() = %d ", refFileSize, iTreeBuffer.Size());
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);
207 aIsIdentical = ETrue;
208 for(TInt iRefBuffer=0; iRefBuffer < bufferSizeToCheck; iRefBuffer++)
210 if(iTreeBuffer[iRefBuffer] != copyRefBuf[iRefBuffer])
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;
219 RDebug::Print(_L("Finished Buffer comparison aIsIdentical=%d"), aIsIdentical);
226 CBaseTestCase::~CBaseTestCase()
235 void CBaseTestCase::SelfComplete()
237 SelfComplete(KErrNone);
240 void CBaseTestCase::SelfComplete(TInt aError)
242 TRequestStatus* s = &iStatus;
243 iStatus = KRequestPending;
244 User::RequestComplete(s,aError);
249 void CBaseTestCase::DoCancel()
263 void CBaseTestCase::RunL()
275 TInt CBaseTestCase::RunError(TInt aError)
278 RDebug::Printf("Test case C%lS::RunL left with %d",&iTestCaseId,aError);
279 iTestPolicy->SignalTestComplete(aError);
283 TDesC& CBaseTestCase::TestCaseId()
289 TInt CBaseTestCase::TestResult() const
294 TBool CBaseTestCase::IsHostOnly() const
299 TBool CBaseTestCase::IsHost() const
304 void CBaseTestCase::PerformTestL()
309 iTreeBuffer.CreateL(KTreeBufferSize); //32k
310 ExecuteHostTestCaseL();
314 ExecuteDeviceTestCaseL();
318 void CBaseTestCase::SetTestPolicy(CBasicTestPolicy* aTestPolicy)
320 iTestPolicy = aTestPolicy;
323 void CBaseTestCase::TestFailed(TInt aFailResult)
326 iTestResult = aFailResult;
329 RDebug::Printf("CActiveScheduler::Stop CBaseTestCase::TestFailed");
330 CActiveScheduler::Stop();
334 void CBaseTestCase::TestPassed()
337 iTestResult = KErrNone;
340 RDebug::Printf("CActiveScheduler::Stop CBaseTestCase::TestPassed");
341 CActiveScheduler::Stop();
345 CBasicTestPolicy& CBaseTestCase::TestPolicy()
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
357 TInt CBaseTestCase::GetEndpointAddress(RUsbInterface& aUsbInterface,TInt aInterfaceSetting,
358 TUint8 aTransferType,TUint8 aDirection,TInt& aEndpointAddress)
362 return GetEndpointAddress(aUsbInterface, aInterfaceSetting, aTransferType, aDirection, 0, aEndpointAddress);
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
370 TInt CBaseTestCase::GetEndpointAddress(RUsbInterface& aUsbInterface,TInt aInterfaceSetting,
371 TUint8 aTransferType,TUint8 aDirection,TUint8 aIndex,TInt& aEndpointAddress)
375 // Get the interface descriptor
376 RDebug::Printf("Getting the interface descriptor for this alternate setting");
378 TUsbInterfaceDescriptor alternateInterfaceDescriptor;
379 TInt err = aUsbInterface.GetAlternateInterfaceDescriptor(aInterfaceSetting, alternateInterfaceDescriptor);
383 RDebug::Printf("<Error %d> Unable to get alternate interface (%d) descriptor",err,aInterfaceSetting);
387 // Parse the descriptor tree from the interface
388 RDebug::Printf("Search the child descriptors for matching endpoint attributes");
390 TUsbGenericDescriptor* descriptor = alternateInterfaceDescriptor.iFirstChild;
391 TUint8 indexCount = 0;
394 RDebug::Printf("Check descriptor type for endpoint");
396 // Cast the descriptor to an endpoint descriptor
397 TUsbEndpointDescriptor* endpoint = TUsbEndpointDescriptor::Cast(descriptor);
401 RDebug::Printf("Match attributes for transfer type");
403 if( (endpoint->Attributes() & aTransferType) == aTransferType)
405 RDebug::Printf("Match attributes for endpoint direction");
407 if( (endpoint->EndpointAddress() & aDirection) == aDirection)
409 if(indexCount==aIndex)
411 aEndpointAddress = endpoint->EndpointAddress();
412 RDebug::Printf("Endpoint address found");
423 descriptor = descriptor->iNextPeer;
426 // Unable to find the endpoint address
427 RDebug::Printf("Unable to find endpoint address matching the specified attributes");
432 /*static*/ void CBaseTestCase::LogWithCondAndInfo(const TDesC& aCondition, const TDesC& aFileName, TInt aLine)
435 buf.Format(KFailText, &aCondition, &aFileName, aLine);
440 /*static*/ void CBaseTestCase::PrintAndStoreTree(TUsbGenericDescriptor& aDesc, TInt aDepth)
444 for(TInt depth=aDepth;depth>=0;--depth)
446 buf.Append(_L8(" "));
449 //##==TBuf16<40> unicodeBuf;
450 TBuf8<40> unicodeBuf;
451 unicodeBuf.Copy(buf); // Ideally this needs conversion to UNICODE
452 if(aDesc.iRecognisedAndParsed == TUsbGenericDescriptor::ERecognised)
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);
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);
463 PrintAndStoreBlob(buf ,aDesc.iBlob);
465 if(aDesc.iFirstChild)
467 RDebug::Printf("%S \\ ", &unicodeBuf);
468 iTreeBuffer.AppendFormat(_L8("%S \\ \n"), &buf);
470 PrintAndStoreTree(*(aDesc.iFirstChild), aDepth+1);
472 RDebug::Printf("%S / ", &unicodeBuf);
473 iTreeBuffer.AppendFormat(_L8("%S / \n"), &buf);
477 PrintAndStoreTree(*(aDesc.iNextPeer), aDepth);
481 void CBaseTestCase::PrintAndStoreBlob(TDes8& aBuf, TPtrC8& aBlob)
484 HBufC8* chunk = HBufC8::New(KChunkSize);
486 TUint nbIter = aBlob.Length()/(KChunkSize/2);
487 TUint remainderSize = aBlob.Length()%(KChunkSize/2);
491 PrintAndStoreChunk(chunk, aBlob.Length() ,aBlob, 0, 0, aBuf );
498 for(i=0;i<nbIter;++i)
500 PrintAndStoreChunk(chunk, (KChunkSize/2) ,aBlob, offset, i, aBuf);
501 offset+=(KChunkSize/2);
504 PrintAndStoreChunk(chunk, remainderSize ,aBlob,offset, i ,aBuf);
509 void CBaseTestCase::PrintAndStoreChunk(HBufC8* aChunk, TUint aSize, TPtrC8& aBlob, TUint aOffset, TUint aIter, TDes8& aBuf)
511 for(TInt i=0;i<aSize;++i)
513 aChunk->Des().AppendFormat(_L8("%02x"), aBlob[i+aOffset]);
516 TBuf16<40> unicodeBuf;
517 unicodeBuf.Copy(aBuf);
518 TBuf16<256> unicodeChunk;
519 unicodeChunk.Copy(aChunk->Des());
523 RDebug::Printf("%S >%S", &unicodeBuf, &unicodeChunk);
524 iTreeBuffer.AppendFormat(_L8("%S >%S\n"), &aBuf, aChunk);
528 RDebug::Printf("%S %S\n", &unicodeBuf, &unicodeChunk);
529 iTreeBuffer.AppendFormat(_L8("%S %S\n"), &aBuf, aChunk);
531 aChunk->Des().Zero();
534 TInt CBaseTestCase::CheckTree(TUsbGenericDescriptor& aDevDesc, TUsbGenericDescriptor& aConfigDesc, const TDesC& aFileName)
542 // print and store tree from aDevDesc & aConfigDesc
543 PrintAndStoreTree(aDevDesc);
544 PrintAndStoreTree(aConfigDesc);
546 // generate file if needed
547 #ifdef GENERATE_TREES
548 GenerateRefFile(aFileName);
549 #endif // GENERATE_TREES
551 // compare tree to ref.
553 if(KErrNone != CompareCurrentTreeToRef(aFileName, isIdentical))
555 RDebug::Printf("CompareCurrentTreeToRef error");
560 RDebug::Printf("!isIdentical");
567 TInt CBaseTestCase::ParseConfigDescriptorAndCheckTree(TUsbDeviceDescriptor *devDesc, const TDesC8& configSet, TUint indexTest)
570 // Parse config. descriptor
571 TUsbGenericDescriptor* parsed = NULL;
572 TInt err = UsbDescriptorParser::Parse(configSet, parsed);
575 RDebug::Printf("parsing error : UsbDescriptorParser::Parse");
578 TUsbConfigurationDescriptor* configDesc = TUsbConfigurationDescriptor::Cast(parsed);
582 RDebug::Printf("configDesc == 0");
587 TBuf<KMaxName> fname(iTestCaseId);
588 fname.AppendFormat(_L("_%d"), indexTest);
589 return CheckTree(*devDesc, *configDesc, fname);
592 TInt CBaseTestCase::CheckTreeAfterDeviceInsertion(CUsbTestDevice& aTestDevice, const TDesC& aFileName)
595 TUsbGenericDescriptor deviceDesc = aTestDevice.DeviceDescriptor();
596 TUsbGenericDescriptor configDesc = aTestDevice.ConfigurationDescriptor();
597 return CheckTree(deviceDesc, configDesc, aFileName);