--- a/kerneltest/e32test/dma/t_dma.cpp Tue Feb 02 01:24:03 2010 +0200
+++ b/kerneltest/e32test/dma/t_dma.cpp Fri Apr 16 16:24:37 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 the License "Eclipse Public License v1.0"
@@ -69,7 +69,7 @@
_LIT(KTestFailure, "XTEST");
static void TestPanic(TInt aLine, TUint32 a1, TUint32 a2, TUint32 a3)
{
- RDebug::Printf("Line %d test failed a1=%08x a2=%08x a3=%08x", aLine, a1, a2, a3);
+ RDebug::Printf("Line %d test failed a1=%08x (%d) a2=%08x (%d) a3=%08x (%d)", aLine, a1, a1, a2, a2, a3, a3);
RThread().Panic(KTestFailure, aLine);
}
#define XTEST(e) if (!(e)) TestPanic(__LINE__, 0, 0, 0)
@@ -193,6 +193,71 @@
const TInt iTotalTransferSize;
};
+/**
+Test that it is possible to close a channel from a callback
+*/
+class CCloseInCb : public CTest
+ {
+public:
+ CCloseInCb()
+ : CTest(NULL, 1), iTransferSize(4 * KKilo)
+ {}
+
+ TInt virtual DoRunTest();
+
+ virtual void AnnounceTest(TDes& aDes)
+ {
+ aDes.AppendFormat(_L("CCloseInCb"));
+ CTest::AnnounceTest(aDes);
+ }
+
+ CTest* Clone() const
+ {return new CCloseInCb(*this);}
+private:
+ const TInt iTransferSize;
+
+ };
+
+/**
+Perform multiple transfers with different fragment counts and with smaller
+and smaller fragment size
+
+This checks that the PSL's ISR(s) are properly written, and do not miss interrupts
+or notify the PIL spuriously.
+*/
+class CFragSizeRange : public CTest
+ {
+public:
+ CFragSizeRange(TInt aMaxIter, TInt aFragCount, TInt aInitialFragmentSize, TInt aInnerIteraions)
+ : CTest(NULL, aMaxIter), iMaxFragCount(aFragCount), iFragCount(1), iInitialFragmentSize(aInitialFragmentSize),
+ iInnerIterations(aInnerIteraions)
+ {}
+
+ TInt virtual DoRunTest();
+
+ virtual void AnnounceTest(TDes& aDes)
+ {
+ aDes.AppendFormat(_L("CFragSizeRange: Fragments %d, intital frag size %d, inner iters %d "), iFragCount, iInitialFragmentSize, iInnerIterations);
+ CTest::AnnounceTest(aDes);
+ }
+
+ CTest* Clone() const
+ {return new CFragSizeRange(*this);}
+
+private:
+ /**
+ Run the transfer
+ */
+ TInt Transfer(TInt aFragSize);
+
+
+ TInt iMaxFragCount;
+ TInt iFragCount;
+ const TInt iInitialFragmentSize;
+ const TInt iInnerIterations;
+
+ RTimer iTimer;
+ };
//
// Active object used to create a tester thread, log on to it and
@@ -346,6 +411,140 @@
return KErrNone;
}
+TInt CCloseInCb::DoRunTest()
+ {
+ TInt r = KErrNone;
+ RTest test(_L("CCloseInCb test"));
+
+ r = OpenChannel(1);
+ test_KErrNone(r);
+
+ const TInt KRequest = 0;
+ const TInt KSrcBuf = 0;
+ const TInt KDestBuf = 1;
+
+ const TInt size = Min(iTransferSize, Info.iMaxTransferSize);
+
+ r = iChannel.AllocBuffer(KSrcBuf, size);
+ test_KErrNone(r);
+ iChannel.FillBuffer(KSrcBuf, 'A');
+ r = iChannel.AllocBuffer(KDestBuf, size);
+ test_KErrNone(r);
+ iChannel.FillBuffer(KDestBuf, '\0');
+
+ TRequestStatus rs = KRequestPending;
+ r = iChannel.Fragment(KRequest, KSrcBuf, KDestBuf, size, &rs);
+ test_KErrNone(r);
+
+ // "X" will cause channel to be closed during callback
+ r = iChannel.Execute(_L8("QX0"));
+ test_KErrNone(r);
+
+ User::WaitForRequest(rs);
+ test_KErrNone(rs.Int());
+
+ test(iChannel.CheckBuffer(KDestBuf, 'A'));
+ iChannel.FreeAllBuffers();
+
+ test.Close();
+ return KErrNone;
+ }
+
+TInt CFragSizeRange::DoRunTest()
+ {
+ const TInt initialFragmentSize = Min(iInitialFragmentSize, Info.iMaxTransferSize);
+
+ TInt r = KErrNone;
+ RTest test(_L("CFragSizeRange test"));
+
+ r = iTimer.CreateLocal();
+ test_KErrNone(r);
+
+
+ TInt fragSize = initialFragmentSize;
+ TInt step = 0;
+ do
+ {
+ fragSize -= step;
+ // make sure size is aligned
+ fragSize = fragSize & ~Info.iMemAlignMask;
+
+ r = OpenChannel(iMaxFragCount, fragSize);
+ test_KErrNone(r);
+
+ for(iFragCount=1; iFragCount <= iMaxFragCount; iFragCount++)
+ {
+ test.Printf(_L("Fragment size %d bytes, %d fragments\nIter: "), fragSize, iFragCount);
+ for(TInt i=0; i<iInnerIterations; i++)
+ {
+
+ test.Printf(_L("%d "), i);
+ r = Transfer(fragSize);
+ test_KErrNone(r);
+
+ }
+ test.Printf(_L("\n"));
+ }
+ iChannel.Close();
+ // Reduce frag size by an eigth each iteration
+ step = (fragSize/8);
+ } while (step > 0);
+
+ iTimer.Close();
+
+ test.Close();
+ return r;
+ }
+
+TInt CFragSizeRange::Transfer(TInt aFragmentSize)
+ {
+ const TInt KRequest = 0;
+ const TInt KSrcBuf = 0;
+ const TInt KDestBuf = 1;
+
+ const TInt size = aFragmentSize * iFragCount;
+
+ TInt r = iChannel.AllocBuffer(KSrcBuf, size);
+ test_KErrNone(r);
+ iChannel.FillBuffer(KSrcBuf, 'A');
+ r = iChannel.AllocBuffer(KDestBuf, size);
+ XTEST2(r == KErrNone, r, size);
+ iChannel.FillBuffer(KDestBuf, '\0');
+
+ // Test simple transfer
+ TRequestStatus rs = KRequestPending;
+ r = iChannel.Fragment(KRequest, KSrcBuf, KDestBuf, size, &rs);
+ test_KErrNone(r);
+
+ test(iChannel.FragmentCheck(KRequest, iFragCount));
+ r = iChannel.Execute(_L8("Q0"));
+ test_KErrNone(r);
+
+ const TInt microSecTimeout = 1000000; // 1s
+ TRequestStatus timerStatus;
+ iTimer.After(timerStatus, microSecTimeout);
+
+ User::WaitForRequest(rs, timerStatus);
+ if(rs.Int() == KRequestPending)
+ {
+ RDebug::Print(_L("Transfer timed out!"));
+ // timed out
+ test(EFalse);
+ }
+ iTimer.Cancel();
+ test_KErrNone(rs.Int());
+ test(iChannel.CheckBuffer(KDestBuf, 'A'));
+
+ // Queue, then cancel request - Checks
+ // that there there is no spurious callback
+ // to the PIL
+ r = iChannel.Execute(_L8("Q0C"));
+ test_KErrNone(r);
+
+ iChannel.FreeAllBuffers();
+ return KErrNone;
+ }
+
// Called when thread completed.
void CTesterThread::RunL()
@@ -414,7 +613,6 @@
if (aMaxThread == 0)
{
- delete aTest;
test.Printf(_L("transfer mode not supported - skipped\n"));
return;
}
@@ -444,9 +642,6 @@
test(new CTesterThread(i, dmaTest) != NULL);
dmaTest = NULL; //ownership transferred to CTesterThread
}
- //the orginal isn't needed
- delete aTest;
- aTest = NULL;
const TTimeIntervalMicroSeconds32 KPeriod = 1000000; // 1s
Bipper->Start(KPeriod, KPeriod, Bip);
@@ -459,17 +654,29 @@
inline void RunSbTest(TInt aMaxThread, CTest* aTest)
{
+ RunTest(Info.iSbChannels, Min(1,Info.iMaxSbChannels), aTest);
RunTest(Info.iSbChannels, Min(aMaxThread,Info.iMaxSbChannels), aTest);
+
+ //the orginal isn't needed
+ delete aTest;
}
inline void RunDbTest(TInt aMaxThread, CTest* aTest)
{
+ RunTest(Info.iDbChannels, Min(1,Info.iMaxDbChannels), aTest);
RunTest(Info.iDbChannels, Min(aMaxThread,Info.iMaxDbChannels), aTest);
+
+ //the orginal isn't needed
+ delete aTest;
}
inline void RunSgTest(TInt aMaxThread, CTest* aTest)
{
+ RunTest(Info.iSgChannels, Min(1,Info.iMaxSgChannels), aTest);
RunTest(Info.iSgChannels, Min(aMaxThread,Info.iMaxSgChannels), aTest);
+
+ //the orginal isn't needed
+ delete aTest;
}
//////////////////////////////////////////////////////////////////////////////
@@ -964,6 +1171,35 @@
test.Next(_L("Getting channel info"));
GetChannelInfo();
+ test.Next(_L("Test that channel can be closed from callback"));
+ test.Next(_L("sb"));
+ RunSbTest(maxchannel, new CCloseInCb() );
+ test.Next(_L("db"));
+ RunDbTest(maxchannel, new CCloseInCb() );
+ test.Next(_L("sg"));
+ RunSgTest(maxchannel, new CCloseInCb() );
+
+ test.Next(_L("Testing different fragment sizes"));
+
+ const TInt rangeFragSize = 4096;
+#ifdef __DMASIM__
+ // Use fewer iterations on the emulator
+ // since it is slower. Also this test is really
+ // intended to find errors in PSL implmentations
+ const TInt iterPerFragSize = 1;
+#else
+ const TInt iterPerFragSize = 30;
+#endif
+ const TInt rangeMaxFragCount = 8;
+
+ test.Next(_L("sb"));
+ RunSbTest(maxchannel, new CFragSizeRange(1, rangeMaxFragCount, rangeFragSize, iterPerFragSize));
+ test.Next(_L("db"));
+ RunDbTest(maxchannel, new CFragSizeRange(1, rangeMaxFragCount, rangeFragSize, iterPerFragSize));
+ test.Next(_L("sg"));
+ RunSgTest(maxchannel, new CFragSizeRange(1, rangeMaxFragCount, rangeFragSize, iterPerFragSize));
+
+
// Size for the single transfer test
TInt totalTransferSize = 64 * KKilo;