diff -r b3a1d9898418 -r 95f71bcdcdb7 kerneltest/e32test/dmav2/t_dma2.cpp --- a/kerneltest/e32test/dmav2/t_dma2.cpp Fri May 14 17:13:29 2010 +0300 +++ b/kerneltest/e32test/dmav2/t_dma2.cpp Thu May 27 14:17:14 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2002-2010 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" @@ -11,7 +11,7 @@ // Contributors: // // Description: -// e32test\dma\t_dma.cpp +// e32test\dmav2\t_dma2.cpp #include "d_dma2.h" #include "u32std.h" @@ -26,18 +26,67 @@ // DMA test framework command parameter options -// SelfTest Option +// SelfTest option _LIT(KArgSelfTest, "/SELFTEST"); _LIT(KArgSelfTest2, "/S"); -//Verbose Option +//Verbose option _LIT(KArgVerboseOutput, "/VERBOSE"); _LIT(KArgVerboseOutput2, "/V"); +//Simple transfer test option +_LIT(KArgSimpleTest, "/simple"); + +//Callback test option +_LIT(KArgCallBackTest, "/callback"); + +//Suspend test option +_LIT(KArgSuspendTest, "/suspend"); + +//Multipart transfer tests +_LIT(KArgMultiPartTest, "/multi"); + +//Isr and dfc test option +_LIT(KArgIsrDfcTest, "/isrdfc"); + +//Isr reque test option +_LIT(KArgIsrequeTest, "/isreque"); + +//Benchmark test option +_LIT(KArgBenchmarkTest, "/bench"); + +//Graphics test option +_LIT(KArgGraphicTest, "/graphic"); + +//DMA channel (opening and closing) test option +_LIT(KArgChannelTest, "/channel"); + +//Queue test option +_LIT(KArgQueueTest, "/queue"); + +//Fragment test option +_LIT(KArgFragmentTest, "/fragment"); + +//Request test option +_LIT(KArgRequestTest, "/request"); + + TBool gHelpRequested; // print usage TBool gVerboseOutput; // enable verbose output TBool gSelfTest; // run SelfTest +TBool gSimpleTest; // run only Simple transfer test +TBool gCallBack; // run only Callback test +TBool gSuspend; // run only Pause and resume tests +TBool gIsrReque; // run only IsrReque tests +TBool gMultiPart; // run only Multipart tests +TBool gIsrAndDfc; // run only IsrAndDfc tests +TBool gBenchmark; // run only Benchmark tests +TBool gGraphic; // run only Graphic tests +TBool gFragment; // run only Fragment related tests +TBool gChannel; // run only Channel(open/close)tests +TBool gQueue; // run only Queue related tests +TBool gRequest; // run only Request related tests /** This function prints out the PSL test Information @@ -77,8 +126,25 @@ void CDmaTest::OpenDmaSession() { - TInt r = iDmaSession.Open(); + // Only open a new session if one + // was not already supplied + if(iDmaSession.Handle() == KNullHandle) + { + TInt r = iDmaSession.Open(); + TEST_ASSERT(r == KErrNone); + r = iDmaSession.OpenSharedChunk(iChunk); + TEST_ASSERT(r == KErrNone); + } + } + +// Open another handle to the test driver +void CDmaTest::OpenDmaSession(const RDmaSession& aSession) + { + iDmaSession = aSession; + TInt r = iDmaSession.Duplicate(RThread(), EOwnerThread); TEST_ASSERT(r == KErrNone); + + // open another handle to the test driver chunk r = iDmaSession.OpenSharedChunk(iChunk); TEST_ASSERT(r == KErrNone); } @@ -89,6 +155,26 @@ iDmaSession.Close(); } +void CDmaTest::PreTransferSetup() + { + } + +TInt CDmaTest::DoPostTransferCheck() + { + return KErrNotSupported; + } + +void CDmaTest::ChannelPause(TUint aChannelSessionCookie) +{ + TInt r = iDmaSession.ChannelPause(aChannelSessionCookie); + TEST_ASSERT(r == KErrNone); +} + +void CDmaTest::ChannelResume(TUint aChannelSessionCookie) +{ + TInt r = iDmaSession.ChannelResume(aChannelSessionCookie); + TEST_ASSERT(r == KErrNone); +} ////////////////////////////////////////////////////////////////////// // CSingleTransferTest ////////////////////////////////////////////////////////////////////// @@ -123,7 +209,7 @@ RDebug::Printf("Calling New Request API\n"); } iActual.iRequestResult.iCreate = - iDmaSession.RequestCreateNew(iChannelSessionCookie, iRequestSessionCookie, iMaxFragmentSize); + iDmaSession.RequestCreate(iChannelSessionCookie, iRequestSessionCookie, iMaxFragmentSize); } else { @@ -132,7 +218,7 @@ RDebug::Printf("Calling Old Request API\n"); } iActual.iRequestResult.iCreate = - iDmaSession.RequestCreate(iChannelSessionCookie, iRequestSessionCookie, iMaxFragmentSize); + iDmaSession.RequestCreateOld(iChannelSessionCookie, iRequestSessionCookie, iMaxFragmentSize); } } @@ -158,7 +244,6 @@ } iActual.iRequestResult.iFragmentationResult = iDmaSession.FragmentRequestOld(iRequestSessionCookie, iTransferArgs); - } const TInt fragmentCount = iDmaSession.RequestFragmentCount(iRequestSessionCookie); @@ -211,6 +296,22 @@ RDebug::RawPrint(_L("Single transfer")); } +void CSingleTransferTest::PrintTestInfo() const + { + CDmaTest::PrintTestInfo(); + + // State which API versions are being used + if(iUseNewFragment) + RDebug::RawPrint(_L(", Fragment v2,")); + else + RDebug::RawPrint(_L(", Fragment v1,")); + + if(iUseNewRequest) + RDebug::RawPrint(_L(" DDmaRequest v2")); + else + RDebug::RawPrint(_L(" DDmaRequest v1")); + } + void CSingleTransferTest::PreTransferSetup() { if(iPreTransfer) @@ -239,18 +340,166 @@ return result; } +////////////////////////////////////////////////////////////////////// +// CDmaTestDecorator +////////////////////////////////////////////////////////////////////// +CDmaTestDecorator::CDmaTestDecorator(CDmaTest* aDecoratedTest) + : CDmaTest(_L("Decorated Test"), 1, NULL, NULL), iDecoratedTest(aDecoratedTest) + {} + +CDmaTestDecorator::CDmaTestDecorator(const CDmaTestDecorator& aOther) + : CDmaTest(aOther), iDecoratedTest( static_cast( aOther.iDecoratedTest->Clone() ) ) + // Need cast because Clone does not have a covariant return type, + // as not all compillers allow it + {} + +////////////////////////////////////////////////////////////////////// +// CMultiVersionTest +////////////////////////////////////////////////////////////////////// + +CMultiVersionTest::CMultiVersionTest(CSingleTransferTest* aDmaTest) + : CDmaTestDecorator(aDmaTest), iNewVersionTest(NULL) + { + } + +CMultiVersionTest::CMultiVersionTest(const CMultiVersionTest& aOther) + : CDmaTestDecorator(aOther), iNewVersionTest( aOther.iNewVersionTest ? static_cast(aOther.iNewVersionTest->Clone()) : NULL) + { + } + +CMultiVersionTest::~CMultiVersionTest() + { + delete iDecoratedTest; + delete iNewVersionTest; + } + +void CMultiVersionTest::SetupL() + { + // Open a tempory dma session to find out the + // capabilities of the dma channel. + OpenDmaSession(); + Configure(); + CloseDmaSession(); + } + +void CMultiVersionTest::Announce() const + { + CTest::Announce(); + + iDecoratedTest->Announce(); + + if(iNewVersionTest) + iNewVersionTest->Announce(); + } + +void CMultiVersionTest::PrintTestType() const + { + RDebug::RawPrint(_L("Multi version test wrapper")); + } + +void CMultiVersionTest::PrintTestInfo() const + { + if(iNewVersionTest) + { + RDebug::RawPrint(_L("Running tests using Version 2 PIL")); + } + else + { + RDebug::RawPrint(_L("Running tests using Version 1 PIL")); + } + } + +void CMultiVersionTest::RunTest() + { + OpenDmaSession(); + + // iDecoratedTest is the test, in the old configuration + // iNewVersionTest is the same test, configured + // to use the new APIs + // + // 2 objects are needed since they can each store + // their own results + + iDecoratedTest->OpenDmaSession(iDmaSession); + (*iDecoratedTest)(); + + if(iNewVersionTest) + { + iNewVersionTest->OpenDmaSession(iDmaSession); + (*iNewVersionTest)(); + } + + CloseDmaSession(); + } + +/** +Maybe create another test object to run with new API + +Pass on the cookie for the channel they must test +*/ +void CMultiVersionTest::Configure() + { + static_cast(iDecoratedTest)->UseNewDmaApi(EFalse); + iDecoratedTest->SetChannelCookie(iChannelCookie); + + if(Version2PILAvailable()) + { + iNewVersionTest = static_cast(iDecoratedTest->Clone()); + TEST_ASSERT(iNewVersionTest != NULL); + + iNewVersionTest->UseNewDmaApi(ETrue); + iNewVersionTest->SetChannelCookie(iChannelCookie); + } + } + +/** +Discover from DMA channel what PIL versions are available. +In practice V1 APIs will always be available, V2 may be. +*/ +TBool CMultiVersionTest::Version2PILAvailable() + { + TUint channelSessionCookie; + TInt r = iDmaSession.ChannelOpen(iChannelCookie, channelSessionCookie); + TEST_ASSERT(r == KErrNone); + + TDmacTestCaps channelCaps; + r = iDmaSession.ChannelCaps(channelSessionCookie, channelCaps); + TEST_ASSERT(r == KErrNone); + + r = iDmaSession.ChannelClose(channelSessionCookie); + TEST_ASSERT(r == KErrNone); + + return channelCaps.iPILVersion >= 2; + } + +TBool CMultiVersionTest::Result() + { + TBool v1Result = iDecoratedTest->Result(); + if(gVerboseOutput || !v1Result) + RDebug::Printf("V1 API result: %s", v1Result ? "success" : "failure"); + + TBool v2Result = iNewVersionTest ? iNewVersionTest->Result() : ETrue; + if(gVerboseOutput || !v1Result) + RDebug::Printf("V2 API result: %s", v2Result ? "success" : "failure"); + return v1Result && v2Result; + } ////////////////////////////////////////////////////////////////////// // CDmaBenchmark ////////////////////////////////////////////////////////////////////// - CDmaBenchmark::CDmaBenchmark(const TDesC& aName, TInt aIterations, const TResultSet& aExpectedResults, const TDmaTransferArgs& aTransferArgs, TUint aMaxFragmentSize) :CSingleTransferTest(aName, aIterations, aTransferArgs, aExpectedResults, aMaxFragmentSize, NULL, NULL) { UseNewDmaApi(EFalse); } +CDmaBenchmark::CDmaBenchmark(const CDmaBenchmark& aOriginal) + :CSingleTransferTest(aOriginal) + { + CopyL(aOriginal.iResultArray, iResultArray); + } + CDmaBenchmark::~CDmaBenchmark() { iResultArray.Close(); @@ -288,17 +537,12 @@ RDebug::Printf(" Mean time: %lu us", MeanResult()); } - //TODO this will be handled by the ctor later - iResultArray.Close(); - return result; } - ////////////////////////////////////////////////////////////////////// // CDmaBmFragmentation ////////////////////////////////////////////////////////////////////// - CDmaBmFragmentation::CDmaBmFragmentation(const TDesC& aName, TInt aIterations, const TDmaTransferArgs& aTransferArgs, TUint aMaxFragmentSize) :CDmaBenchmark(aName, aIterations, ExpectedResults, aTransferArgs, aMaxFragmentSize) {} @@ -331,21 +575,334 @@ Fragment(); FreeRequest(); CloseChannel(); + CloseDmaSession(); + } + +////////////////////////////////////////////////////////////////////// +// CPauseResumeTest +// +// -Time how long a given transfer takes +// -Pause the channel +// -repeat the transfer (queued asynchronously) +// -wait for some time (say, 3 times the time measured) +// -read the value of the TRequestStatus object, to check it is still pending +// -resume the channel +// -Wait on the request +// -Confirm that the request completed +////////////////////////////////////////////////////////////////////// +CPauseResumeTest::~CPauseResumeTest() + { + } + +void CPauseResumeTest::RunTest() + { + OpenDmaSession(); + + //Open a single DMA channel for a transfer + OpenChannel(); + + RDebug::Printf("Resume unpaused idle channel"); + TInt r = iDmaSession.ChannelResume(iChannelSessionCookie); + TEST_ASSERT(KErrCompletion == r); + + RDebug::Printf("Pause idle channel"); + r = iDmaSession.ChannelPause(iChannelSessionCookie); + TEST_ASSERT(KErrNone == r); + + RDebug::Printf("Pause paused idle Channel"); + r = iDmaSession.ChannelPause(iChannelSessionCookie); + TEST_ASSERT(KErrCompletion == r); + + RDebug::Printf("Resume paused idle channel"); + r = iDmaSession.ChannelResume(iChannelSessionCookie); + TEST_ASSERT(KErrNone == r); + + //Setup a DMA request and Fragment the request. + CreateDmaRequest(); + Fragment(); + + //Queue the DMA request and time how long a transfer takes + TUint64 queueTime; + DoCalibrationTransfer(queueTime); + + RDebug::Printf("Calibration transfer completed in %Lu us",queueTime); + TUint32 waitQueueReqTime = I64LOW(queueTime*3); //3 times the time measured in DoCalibrationTransfer + TEST_ASSERT(I64HIGH(queueTime*3) == 0); // If transfer takes over an hour, something has gone wrong anyway + + // Initialise buffers, after calibration transfer + PreTransferSetup(); + + RDebug::Printf("Resume unpaused channel"); + r = iDmaSession.ChannelResume(iChannelSessionCookie); + TEST_ASSERT(KErrCompletion == r); + + //Pause DMA Transfer + RDebug::Printf("Pausing DMA Channel"); + r = iDmaSession.ChannelPause(iChannelSessionCookie); + TEST_ASSERT(KErrNone == r); + + RDebug::Printf("Pause paused Channel"); + r = iDmaSession.ChannelPause(iChannelSessionCookie); + TEST_ASSERT(KErrCompletion == r); + + //Repeat the transfer (queued asynchronously) + TRequestStatus queueRequestStatus; + iActual.iRequestResult.iQueueResult = QueueAsyncRequest(queueRequestStatus,queueTime); + RDebug::Printf("Queue a DMA Request and wait for %u us ", waitQueueReqTime); + + User::After(waitQueueReqTime); + RDebug::Printf("Finished waiting"); + TEST_ASSERT(queueRequestStatus.Int() == KRequestPending); + + TBool queueEmpty = ETrue; + r = iDmaSession.ChannelIsQueueEmpty(iChannelSessionCookie,queueEmpty); + TEST_ASSERT(r == KErrNone); + TEST_ASSERT(!queueEmpty); + + //Resume DMA channel + RDebug::Printf("Resuming paused DMA Channel"); + r = iDmaSession.ChannelResume(iChannelSessionCookie); + TEST_ASSERT(KErrNone == r); + + //Wait for transfer to complete + User::WaitForRequest(queueRequestStatus); + if (queueRequestStatus.Int() == KErrNone) + { + RDebug::Printf("DMA QueueAsyncRequest completed"); + } + + FreeRequest(); + CloseChannel(); + + PostTransferCheck(); + CloseDmaSession(); + } + +/** +Time how long transfer takes, with no pausing +*/ +void CPauseResumeTest::DoCalibrationTransfer(TUint64 &atime) + { + //Queue the DMA request. + TCallbackRecord pCallbackRecord; + TInt r = iDmaSession.QueueRequest(iRequestSessionCookie,&pCallbackRecord,&atime); + TEST_ASSERT(r == KErrNone); + } + +TInt CPauseResumeTest::QueueAsyncRequest(TRequestStatus &aRequestState, TUint64 &atime) + { + return iDmaSession.QueueRequest(iRequestSessionCookie,aRequestState, &iActual.iCallbackRecord, &atime); + } + +void CPauseResumeTest::PrintTestType() const + { + RDebug::RawPrint(_L("Pause and Resume API Test")); + } + +////////////////////////////////////////////////////////////////////// +// COpenCloseTest +////////////////////////////////////////////////////////////////////// +COpenCloseTest::~COpenCloseTest() + { + } + +TBool COpenCloseTest::DoRunClose() + { + // For storing cookie during neagtive test i,e open channel twice + TUint testChannelSessionCookie = 0; + + // Open a single DMA channel + TInt r = iDmaSession.ChannelOpen(iChannelCookie, iChannelSessionCookie); + if (r == KErrNone)//Check that DMA channel opened with no errors + { + RDebug::Printf("DMA channel opened"); + } + else + { + RDebug::Printf("Open DMA channel failed"); + return EFalse; + } + + // Open DMA channel again and check that opening DMA channel again fails + r = iDmaSession.ChannelOpen(iChannelCookie, testChannelSessionCookie); + if (r == KErrInUse) + { + RDebug::Printf("Opening DMA channel again fails as expected"); + } + else + { + RDebug::Printf("Open DMA channel again failed"); + return EFalse; + } + + // Close the DMA channel and check that DMA channel closes with no errors + r =iDmaSession.ChannelClose(iChannelSessionCookie); + if (r == KErrNone) + { + RDebug::Printf("DMA channel closes with no errors"); + } + else + { + RDebug::Printf("Close the DMA channel failed"); + return EFalse; + } + + // Verify that the DMA channel was actually closed by opening DMA channel + r = iDmaSession.ChannelOpen(iChannelCookie, iChannelSessionCookie); + if (r == KErrNone) + { + RDebug::Printf("DMA channel opened after a previous close operation"); + return ETrue; + } + else + { + RDebug::Printf("Open DMA channel to verify that the DMA channel closed failed"); + return EFalse; + } + } + +TBool COpenCloseTest::DoRunOpen() + { + // Open a single DMA channel + TInt r = iDmaSession.ChannelOpen(iChannelCookie, iChannelSessionCookie); + if (r == KErrNone)//Check that DMA channel opened with no errors + { + RDebug::Printf("DoRunOpen:DMA channel opened"); + } + else + { + RDebug::Printf("DoRunOpenDMA channel failed to open"); + return EFalse; + } + + // Verify that channel is really open by closing DMA channel + // and checking that DMA channel closes with no errors + r = iDmaSession.ChannelClose(iChannelSessionCookie); + if (r == KErrNone) + { + RDebug::Printf("DoRunOpen:DMA channel closes with no errors"); + return ETrue; + } + else + { + RDebug::Printf("DoRunOpen:DMA channel failed to close"); + return EFalse; + } + } + +TBool COpenCloseTest::DoRunOpenExposed() + { + SCreateInfoTest TOpenInfo; + TOpenInfo.iCookie =iChannelCookie; + TOpenInfo.iDfcPriority = 3; + + const TInt desCount[3] = {0,1,128}; + const TBool dynChannel[3] = {EFalse,EFalse,ETrue}; + const TInt expectedResults[3] = {KErrArgument,KErrNone,KErrInUse}; + TInt actualResults[3] = {1, 1, 1}; + + for (TInt i =0; i<3; i++) + { + TOpenInfo.iDesCount = desCount[i]; + TOpenInfo.iDynChannel = dynChannel[i]; + + // Open a single DMA channel + RDebug::Printf("DoRunOpenExposed:Trying to open DMA channel using iDesCount(%d) and iDynChannel(%d) ", TOpenInfo.iDesCount,TOpenInfo.iDynChannel); + actualResults[i] = iDmaSession.ChannelOpen(iChannelSessionCookie, TOpenInfo); + if (actualResults[i] == KErrNone)// Verify that channel is really open by closing DMA channel + { + TInt err = iDmaSession.ChannelClose(iChannelSessionCookie); + TEST_ASSERT(err == KErrNone)//Check that DMA channel closed with no errors + } + } + + // This case should fail if idesCount = 0. + // PIL has been changed to return KErrArgument instead of using an assertion check + if (expectedResults[0] == actualResults[0]) + { + RDebug::Printf("DoRunOpenExposed:DMA channel failed to open as expected as for iDesCount = 0 "); + } + else + { + RDebug::Printf("DoRunOpenExposed:Error code returned (%d), expected KErrArgument as iDesCount= 0) ", actualResults[0]); + return EFalse; + } + + // For this case( idesCount = 1), DMA channel should open with no issues + if (expectedResults[1] == actualResults[1]) + { + RDebug::Printf("DoRunOpenExposed:DMA channel closes with no errors as expected for iDesCount = 1 "); + } + else + { + RDebug::Printf("DoRunOpenExposed:Failed to open DMA channel with error code (%d)", actualResults[1]); + return EFalse; + } + + // For this case(dynaChannel=ETrue), DMA channel now returns KErrInUse. dynaChannel is not supported in the PSL. + // PSL now returns a NULL pointer when dynaChannel is requested. The PIL interprets a NULL + // pointer being returned from opening a DMA channel as a channel in use. Hence, KErrInUse is returned. + if (expectedResults[2] == actualResults[2]) + { + RDebug::Printf("DoRunOpenExposed:DMA channel failed to open as expected as dynamic channel is not supported"); + } + else + { + RDebug::Printf("DoRunOpenExposed:Error code returned (%d), expected KErrInUse as as dynamic channel is not supported", actualResults[2]); + return EFalse; + } + + return ETrue; + } + +void COpenCloseTest::RunTest() + { + OpenDmaSession(); + + if (iRunOpen) + { // Run Open() API test + iOpenCloseResult = DoRunOpenExposed(); + if(iOpenCloseResult) + iOpenCloseResult = DoRunOpen(); + } + else + { + // Run Close() API test + iOpenCloseResult = DoRunClose(); + } CloseDmaSession(); } +void COpenCloseTest::PrintTestType() const + { + RDebug::RawPrint(_L("Close/Open API Test")); + + } + +TBool COpenCloseTest::Result() + { + if(gVerboseOutput) + { + RDebug::Printf("Results for Close/Open API Test"); + } + + if(!iOpenCloseResult) + { + RDebug::Printf("Open/Close test sequence failed"); + } + + return iOpenCloseResult; + } ////////////////////////////////////////////////////////////////////// // CDmaBmTransfer ////////////////////////////////////////////////////////////////////// - CDmaBmTransfer::CDmaBmTransfer(const TDesC& aName, TInt aIterations, const TDmaTransferArgs& aTransferArgs, TUint aMaxFragmentSize) :CDmaBenchmark(aName, aIterations, TResultSet(KErrNone, TRequestResults(), KErrUnknown, TCallbackRecord(TCallbackRecord::EThread,1)), aTransferArgs, aMaxFragmentSize) {} - void CDmaBmTransfer::PrintTestType() const { RDebug::RawPrint(_L("Transfer Benchmark")); @@ -375,13 +932,247 @@ } } +/* +1. Open a DMA channel for a transfer. +2. Queue multiple request on the DMA channel. +3. Call CancelAll () on the DMA channel. +4. Verify that all transfers have been cancelled. +5. Open a DMA channel for a transfer. This channel should support pause and resume. +6. Call Pause () on the channel. +7. Queue multiple request on the DMA channel. +8. Call CancelAll () on the channel. +9. Verify that all transfers have been cancelled. + + Note: This check does not add results to TResultSet like some + other tests as its operation is different. The test checks for + the the cancelllation of all transfers queued on a channel by + calling iDmaSession.ChannelIsQueueEmpty(); +*/ + +////////////////////////////////////////////////////////////////////// +// CCancelAllTest +////////////////////////////////////////////////////////////////////// + + +CCancelAllTest::CCancelAllTest(const TDesC& aName, TInt aIterations, + const TDmaTransferArgs* aTransferArgs, const TResultSet* aResultSets, + TInt aCount) + :CMultiTransferTest(aName, aIterations, aTransferArgs, aResultSets, aCount) + {} + +void CCancelAllTest::RunTest() + { + OpenDmaSession(); + PreTransferSetup(); + + // Open a DMA channel for a transfer.This channel should support pause and resume. + OpenChannel(); + + //Call Pause () on the channel + RDebug::Printf("Pausing DMA Channel"); + ChannelPause(iChannelSessionCookie); + + // Queue multiple request on the DMA channel. + CreateDmaRequests(); + Fragment(); + + QueueRequestsAsync(); + + // Call CancelAll () on the DMA channel and Verify that all transfers have been cancelled. + TInt r = CancelAllRequests(); + TEST_ASSERT(r == KErrNone); + + //Call Resume () on the channel. + RDebug::Printf("Cancel should clear Pause state: resuming channel should fail"); + ChannelResume(iChannelSessionCookie); + //TEST_ASSERT(r == KErrCompletion); + + r = DoPostTransferCheck(); + TEST_ASSERT(r == KErrNone); + //Destroy request + for(TInt i=0; i<2; i++) + { + r = iDmaSession.RequestDestroy(iRequestCookies[i]); + TEST_ASSERT(r == KErrNone); + } + + //Close DMA channel + CloseChannel(); + + CloseDmaSession(); + } + +TInt CCancelAllTest::CancelAllRequests() + { + if(gVerboseOutput) + { + RDebug::Printf("CCancelAllTest::CancelAllRequests()"); + } + TInt r = KErrGeneral; + r = iDmaSession.ChannelCancelAll(iChannelSessionCookie); + if (r != KErrNone) + return r; + + TBool queueEmpty; + r = iDmaSession.ChannelIsQueueEmpty(iChannelSessionCookie,queueEmpty); + if (r != KErrNone) + return r; + + if(!queueEmpty) + return KErrGeneral; + + if(gVerboseOutput) + { + RDebug::Printf("Both current and pending requests cancelled"); + } + return KErrNone; + } + +void CCancelAllTest::PrintTestType() const + { + RDebug::RawPrint(_L("CCancelAllTest")); + } + +void CCancelAllTest::QueueRequestsAsync() + { + if(iPauseWhileQueuing) + { + TInt r = iDmaSession.ChannelPause(iChannelSessionCookie); + TEST_ASSERT(r == KErrNone); + } + + // Queue all the DMA requests asynchronously + TEST_ASSERT(iActualResults.Count() == iTransferArgsCount); + for(TInt i=0; i requestStates; + + ChannelPause(iChannelSessionCookie); + DoIsQueueEmpty(); + + TEST_ASSERT(iActualResults.Count() == iTransferArgsCount); + for(i=0; i(&aOther.iRequestCookies[0]), aOther.iRequestCookies.Count()) { + CopyL(aOther.iRequestCookies, iRequestCookies); } CMultiTransferTest::~CMultiTransferTest() @@ -497,10 +1286,13 @@ TEST_ASSERT(iActualResults.Count() == iTransferArgsCount); for(TInt i=0; i(aChunkBase)); + const TAddrRange destination = parms.DestRange(); + + return destination.IsFilled(0); + } ////////////////////////////////////////////////////////////////////// // MPreTransfer classes ////////////////////////////////////////////////////////////////////// - void TPreTransferIncrBytes::Setup(const CSingleTransferTest& aTest) const { if(gVerboseOutput) @@ -904,7 +1743,12 @@ { RDebug::Printf("TPreTransferIncrBytes(CMultiTransferTest)"); } - //TODO check for overlap + + if(!CheckBuffers(aTest)) + { + RDebug::Printf("Successive transfer destinations may not overlap previous src or dst buffers"); + TEST_FAULT; + } TUint8* const chunkBase = aTest.Chunk().Base(); const TInt transferCount = aTest.TransferCount(); @@ -943,26 +1787,85 @@ } /** +A CMultiTransferTest will wait for all transfers to complete +before comapairing source and destination buffers. For this to be successful +each transfer must be independent ie. no destination or source may be +overwritten by another transfer and source buffers may not depend on an +earlier transfer +*/ +TBool TPreTransferIncrBytes::CheckBuffers(const CMultiTransferTest& aTest) const + { + TUint8* const chunkBase = aTest.Chunk().Base(); + const TInt transferCount = aTest.TransferCount(); + + // assemble an array of TAddressParams from aTest, that + // can then be passed to CheckBuffers(RArray) + RArray array; + + for(TInt i=0; i aTransferParams) const +TBool TPreTransferIncrBytes::CheckBuffers(const RArray& aTransferParams, TBool aAllowExactRepeat) const { + const TInt count = aTransferParams.Count(); + if(gVerboseOutput) + { + RDebug::Printf("CheckBuffers, %d transfers", count); + } + + TBuf<128> buf; for(TInt i=1; iiElementSize; RTest test(_L("TTransferIter invariant")); - const TInt bytesTransfered = ( + const TUint bytesTransfered = ( elemSize * (iFrame * iCfg->iElementsPerFrame + iElem) + ((TUint)iPtr % (elemSize)) ); @@ -1237,9 +2139,6 @@ //Here, we must create a test thread for each channel RPointerArray concurrentTests; - if(testCase.iConcurrentTest) - RDebug::Printf("== Begin concurrent test run =="); - const TInt chanRecCount = iChannelRecords.Count(); for(TInt j=0; j < chanRecCount; j++) { @@ -1256,7 +2155,7 @@ TEST_ASSERT(dmaTest != NULL); dmaTest->SetChannelCookie(record.iCookie); - dmaTest->Announce(); + dmaTest->SetupL(); if(testCase.iConcurrentTest) { //Add test to array to be run concurrently @@ -1265,9 +2164,9 @@ } else { + dmaTest->Announce(); //Run test in this thread (*dmaTest)(); - //TTestThread( TBool result = dmaTest->Result(); TEST_ASSERT(result); @@ -1297,11 +2196,20 @@ //if the test case has been run on all channels it will then wait for all threads to complete. } + // Run the tests which should happen concurrently const TInt count = concurrentTests.Count(); if(count>0) { + RDebug::Printf("== Begin concurrent test run =="); + + TInt i; // VC++ + for(i=0; iAnnounce(); + } + MultipleTestRun(concurrentTests); - for(TInt i=0; i(concurrentTests[i])->Result(); TEST_ASSERT(result); @@ -1374,8 +2282,20 @@ { test.Printf(_L("*** DMA TEST FRAMEWORK ***\n")); test.Printf(_L("Usage : t_dma2.exe [/option]\n")); - test.Printf(_L(" /V or /VERBOSE = Control test output\n")); - test.Printf(_L(" /S or /SELFTEST = Run DMA self test\n")); + test.Printf(_L(" /V or /VERBOSE = Control test output\n")); + test.Printf(_L(" /S or /SELFTEST = Run DMA self tests\n")); + test.Printf(_L(" /simple = Run only simple transfer tests\n")); + test.Printf(_L(" /callback = Run only callback tests\n")); + test.Printf(_L(" /multi = Run only multipart transfer tests\n")); + test.Printf(_L(" /isrdfc = Run only isr and dfc tests\n")); + test.Printf(_L(" /isreque = Run only isr reque tests\n")); + test.Printf(_L(" /bench = Run only benchmark tests\n")); + test.Printf(_L(" /suspend = Run only pause and resume tests\n")); + test.Printf(_L(" /graphic = Run only graphic tests\n")); + test.Printf(_L(" /channel = Run only DMA channel (opening and closing) tests\n")); + test.Printf(_L(" /queue = Run only queue tests\n")); + test.Printf(_L(" /fragment = Run only fragmentation related tests\n")); + test.Printf(_L(" /request = Run only requests tests related tests\n")); test.Printf(_L("\n")); } @@ -1424,6 +2344,90 @@ tokenParsed = ETrue; } + // '/suspend' option + if ((0== tc->FindF(KArgSuspendTest))) + { + gSuspend = ETrue; + tokenParsed = ETrue; + } + + // '/simple' option + if ((0== tc->FindF(KArgSimpleTest))) + { + gSimpleTest = ETrue; + tokenParsed = ETrue; + } + + // '/multi' option + if ((0== tc->FindF(KArgMultiPartTest))) + { + gMultiPart = ETrue; + tokenParsed = ETrue; + } + + // '/callback' option + if ((0== tc->FindF(KArgCallBackTest))) + { + gCallBack = ETrue; + tokenParsed = ETrue; + } + + // '/IsrAndDfc' option + if ((0== tc->FindF(KArgIsrDfcTest))) + { + gIsrAndDfc = ETrue; + tokenParsed = ETrue; + } + + // '/IsrReque' option + if ((0== tc->FindF(KArgIsrequeTest))) + { + gIsrReque = ETrue; + tokenParsed = ETrue; + } + + // '/Benchmark' option + if ((0== tc->FindF(KArgBenchmarkTest))) + { + gBenchmark = ETrue; + tokenParsed = ETrue; + } + + // '/Queue' option + if ((0== tc->FindF(KArgQueueTest))) + { + gQueue = ETrue; + tokenParsed = ETrue; + } + + // '/Fragment' option + if ((0== tc->FindF(KArgFragmentTest))) + { + gFragment = ETrue; + tokenParsed = ETrue; + } + + // '/Channel' option + if ((0== tc->FindF(KArgChannelTest))) + { + gChannel = ETrue; + tokenParsed = ETrue; + } + + // '/Graphic' option + if ((0== tc->FindF(KArgGraphicTest))) + { + gGraphic = ETrue; + tokenParsed = ETrue; + } + + // '/Request' option + if ((0== tc->FindF(KArgRequestTest))) + { + gRequest = ETrue; + tokenParsed = ETrue; + } + if (!tokenParsed) { // warn about unparsed parameter @@ -1444,8 +2448,61 @@ TTestRunner testRunner; test.Next(_L("Add global test cases to test runner\n")); - testRunner.AddTestCases(TestArray); + if (gSimpleTest) //Add only simple tranfer test cases + { + testRunner.AddTestCases(TestArraySimple); + } + else if (gCallBack) //Add only callback test cases + { + testRunner.AddTestCases(TestArrayCallback); + } + else if (gIsrReque) //Add only ISR Reque test cases + { + testRunner.AddTestCases(TestArrayIsrReque); + } + else if (gMultiPart) //Add only Multipart test cases + { + testRunner.AddTestCases(TestArrayMultiPart); + } + else if (gIsrAndDfc) //Add only IsrAndDfc test cases + { + testRunner.AddTestCases(TestArrayIsrAndDfc); + } + else if (gBenchmark) //Add only Benchmark test cases + { + testRunner.AddTestCases(TestArrayBenchmark); + } + else if (gGraphic) //Add only 2D test cases + { + testRunner.AddTestCases(TestArray2DTest); + } + else if (gFragment) //Add only Fragment test cases + { + testRunner.AddTestCases(TestArrayFragment); + } + else if (gChannel) //Add only Channel test cases + { + testRunner.AddTestCases(TestArrayChannel); + } + else if (gSuspend) //Add only Suspend test cases + { + testRunner.AddTestCases(TestArraySuspend); + } + else if (gQueue) //Add only queue test cases + { + testRunner.AddTestCases(TestArrayQueue); + } + else if (gRequest) //Add only request test cases + { + testRunner.AddTestCases(TestArrayRequest); + } + else + { + testRunner.AddTestCases(TestArray);//Add all test cases + } + + test.Next(_L("call TTestRunner::RunTests()\n")); testRunner.RunTests(); @@ -1455,7 +2512,6 @@ TInt E32Main() { __UHEAP_MARK; - //__KHEAP_MARK; test.Title(); gHelpRequested = EFalse; @@ -1495,10 +2551,7 @@ if (!(dma2Loaded || dma2CompatLoaded)) { - //TODO how can we distinguish this case from a platform where - //dma is supposed to be supported but the dma test ldd is - //missing? - test.Printf(_L("DMA not supported - test skipped\n")); + test.Printf(_L("DMA test driver not found - test skipped\n")); return 0; } else if (dma2Loaded && !dma2CompatLoaded) @@ -1527,10 +2580,12 @@ SelfTests(); } - ApiTests(); - RunDMATests(); + // Wait for the supervisor thread to run and perform asynchronous + // cleanup, so that kernel heap space will be freed + r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, (TAny*)5000, 0); + test_KErrNone(r); __KHEAP_MARKEND; r = User::FreeLogicalDevice(KTestDmaLddName); @@ -1540,7 +2595,6 @@ delete cleanup; - //__KHEAP_MARKEND; __UHEAP_MARKEND; return 0; }