sl@0: // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test/mmu/t_shbuf.cpp sl@0: // sl@0: sl@0: #define __E32TEST_EXTENSION__ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "d_shbuf.h" sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #ifdef TEST_CLIENT_THREAD sl@0: RTest test(_L("T_SHBUF_CLIENT")); sl@0: #else sl@0: RTest test(_L("T_SHBUF_OWN")); sl@0: #endif sl@0: sl@0: RShPool P1; // User-side pool sl@0: RShPool P2; // Kernel-side pool sl@0: sl@0: const TInt KTestPoolSizeInBytes = 1 << 20; // 1MB sl@0: const TInt BufferSize[] = {128, 853, 4096, 5051, 131072, 1, 0}; // Last element must be 0 sl@0: sl@0: const TInt* PtrBufSize; sl@0: sl@0: RShBufTestChannel Ldd; sl@0: sl@0: _LIT(KTestSlave, "SLAVE"); sl@0: _LIT(KTestLowSpaceSemaphore, "LowSpaceSemaphore"); sl@0: sl@0: enum TTestSlave sl@0: { sl@0: ETestSlaveError, sl@0: ETestSlaveNoDeallocation, sl@0: }; sl@0: sl@0: enum TTestPoolType sl@0: { sl@0: ETestNonPageAligned, sl@0: ETestPageAligned, sl@0: ETestPageAlignedGrowing, sl@0: }; sl@0: sl@0: TInt Log2(TInt aNum) sl@0: { sl@0: TInt res = -1; sl@0: while(aNum) sl@0: { sl@0: res++; sl@0: aNum >>= 1; sl@0: } sl@0: return res; sl@0: } sl@0: sl@0: TInt RoundUp(TInt aNum, TInt aAlignmentLog2) sl@0: { sl@0: if (aNum % (1 << aAlignmentLog2) == 0) sl@0: { sl@0: return aNum; sl@0: } sl@0: return (aNum & ~((1 << aAlignmentLog2) - 1)) + (1 << aAlignmentLog2); sl@0: } sl@0: sl@0: void LoadDeviceDrivers() sl@0: { sl@0: TInt r; sl@0: #ifdef TEST_CLIENT_THREAD sl@0: r= User::LoadLogicalDevice(_L("D_SHBUF_CLIENT.LDD")); sl@0: if (r != KErrAlreadyExists) sl@0: { sl@0: test_KErrNone(r); sl@0: } sl@0: #else sl@0: r = User::LoadLogicalDevice(_L("D_SHBUF_OWN.LDD")); sl@0: if (r != KErrAlreadyExists) sl@0: { sl@0: test_KErrNone(r); sl@0: } sl@0: #endif sl@0: } sl@0: sl@0: void FreeDeviceDrivers() sl@0: { sl@0: TInt r = User::FreeLogicalDevice(KTestShBufClient); sl@0: test_KErrNone(r); sl@0: r = User::FreeLogicalDevice(KTestShBufOwn); sl@0: test_KErrNone(r); sl@0: } sl@0: sl@0: void FillShBuf(RShBuf& aBuffer, TUint8 aValue) sl@0: { sl@0: TUint size = aBuffer.Size(); sl@0: TUint8* base = aBuffer.Ptr(); sl@0: test(size!=0); sl@0: test(base!=0); sl@0: memset(base,aValue,size); sl@0: } sl@0: sl@0: TBool CheckFillShBuf(RShBuf& aBuffer, TUint8 aValue) sl@0: { sl@0: TUint size = aBuffer.Size(); sl@0: TUint8* base = aBuffer.Ptr(); sl@0: test(size!=0); sl@0: test(base!=0); sl@0: TUint8* ptr = base; sl@0: TUint8* end = ptr+size; sl@0: while(ptr tmp; sl@0: sl@0: P1.GetInfo(poolinfo1); sl@0: blocks = poolinfo1.iBufSize / tmp.MaxSize(); sl@0: sl@0: for (i = 0 ; i < blocks; i++) sl@0: { sl@0: tmp.Fill(i); sl@0: TPtrC8 ptrc(buf.Ptr() + (i * tmp.Length()), tmp.Length()); sl@0: r = tmp.Compare(ptrc); sl@0: test_Equal(0, r); sl@0: } sl@0: buf.Close(); sl@0: __KHEAP_MARKEND; sl@0: sl@0: // Allocate buffer on POOL 2 sl@0: __KHEAP_MARK; sl@0: r = buf.Alloc(P2); sl@0: test_KErrNone(r); sl@0: __KHEAP_CHECK(0); sl@0: sl@0: TShPoolInfo poolinfo2; sl@0: P2.GetInfo(poolinfo2); sl@0: blocks = poolinfo2.iBufSize / KTestData1().Length(); // PC REMOVE sl@0: sl@0: for (i = 0; i < blocks; i++) sl@0: { sl@0: TPtr8(buf.Ptr() + (i * KTestData1().Length()), KTestData1().Length(),KTestData1().Length()).Copy(KTestData1()); sl@0: } sl@0: sl@0: r = Ldd.ManipulateUserBuffer(buf.Handle()); sl@0: test_KErrNone(r); sl@0: sl@0: P2.GetInfo(poolinfo2); sl@0: blocks = poolinfo2.iBufSize / tmp.MaxSize(); // PC REMOVE sl@0: sl@0: for (i = 0 ; i < blocks; i++) sl@0: { sl@0: tmp.Fill(i); sl@0: r = tmp.Compare(TPtr8(buf.Ptr() + (i * tmp.Length()), tmp.Length(), tmp.Length())); sl@0: test_Equal(0, r); sl@0: } sl@0: buf.Close(); sl@0: __KHEAP_MARKEND; sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID 4 sl@0: @SYMTestCaseDesc Buffer allocation from kernel-side sl@0: @SYMREQ REQ11423 sl@0: @SYMTestActions sl@0: 1. Device Driver creates a buffer on P2. sl@0: 2. Device Driver manipulates buffer and passes it to Test Thread. sl@0: 3. Test Thread manipulates buffer and send it back to Device Driver. sl@0: 4. Device Driver check buffer's contents and releases it. sl@0: @SYMTestExpectedResults sl@0: 1. Ok. sl@0: 2. Ok. sl@0: 3. Ok. sl@0: 4. Ok. Buffer de-allocated. sl@0: @SYMTestPriority Critical sl@0: */ sl@0: sl@0: void AllocateKernelBuffer() sl@0: { sl@0: test.Next(_L("Allocate kernel-side buffer")); sl@0: TInt r; sl@0: TInt handle; sl@0: RShBuf kbuf0, kbuf1; sl@0: sl@0: // Allocate buffer on POOL 1 sl@0: r = Ldd.AllocateKernelBuffer(0, handle); sl@0: test_KErrNone(r); sl@0: kbuf0.SetHandle(handle); sl@0: sl@0: TInt i; sl@0: TShPoolInfo poolinfo1; sl@0: P1.GetInfo(poolinfo1); sl@0: TInt blocks = poolinfo1.iBufSize / KTestData2().Length(); sl@0: for (i = 0; i < blocks; i++) sl@0: { sl@0: r = KTestData2().Compare(TPtr8(kbuf0.Ptr() + (i * KTestData2().Length()), KTestData2().Length(), KTestData2().Length())); sl@0: sl@0: test_Equal(0, r); sl@0: } sl@0: kbuf0.Close(); sl@0: sl@0: // Allocate buffer on POOL 2 sl@0: r = Ldd.AllocateKernelBuffer(1, handle); sl@0: test_KErrNone(r); sl@0: kbuf1.SetHandle(handle); sl@0: sl@0: TShPoolInfo poolinfo2; sl@0: P2.GetInfo(poolinfo2); sl@0: blocks = poolinfo2.iBufSize / KTestData2().Length(); sl@0: sl@0: for (i = 0; i < blocks; i++) sl@0: { sl@0: r = KTestData2().Compare(TPtr8(kbuf1.Ptr() + (i * KTestData2().Length()), KTestData2().Length(), KTestData2().Length())); sl@0: sl@0: test_Equal(0, r); sl@0: } sl@0: kbuf1.Close(); sl@0: } sl@0: sl@0: sl@0: /* sl@0: @SYMTestCaseID X1 sl@0: @SYMTestCaseDesc Allocate maximum number of buffers in a pool (user/kernel) sl@0: @SYMREQ REQ11423 sl@0: @SYMTestActions sl@0: Allocate as many buffers on a pool as possible. sl@0: Free them all and re-allocate them again. sl@0: Free them all. sl@0: @SYMTestExpectedResults sl@0: Ok. sl@0: @SYMTestPriority High sl@0: */ sl@0: sl@0: void AllocateUserMax(RShPool& aPool) sl@0: { sl@0: test.Next(_L("Exhaust pool memory from user-side")); sl@0: TInt r; sl@0: sl@0: TShPoolInfo poolinfo; sl@0: aPool.GetInfo(poolinfo); sl@0: TBool aligned = (poolinfo.iFlags & EShPoolPageAlignedBuffer); sl@0: RDebug::Printf("aligned=%d",aligned); sl@0: sl@0: RArray bufarray; sl@0: do sl@0: { sl@0: RShBuf buf; sl@0: r = buf.Alloc(aPool); sl@0: if (r==KErrNoMemory && KTestPoolSizeInBufs>bufarray.Count()) sl@0: { sl@0: // try again after a delay, to allow for background resource allocation sl@0: sl@0: User::After(1000000); sl@0: r = buf.Alloc(aPool); sl@0: } sl@0: if (!r) sl@0: { sl@0: r = bufarray.Append(buf); sl@0: test_KErrNone(r); sl@0: FillShBuf(buf,0x99); sl@0: } sl@0: } sl@0: while (r == KErrNone); sl@0: test_Equal(KErrNoMemory, r); sl@0: test_Compare(KTestPoolSizeInBufs, <=, bufarray.Count()); sl@0: sl@0: TInt n = bufarray.Count(); sl@0: while (n) sl@0: { sl@0: bufarray[--n].Close(); sl@0: } sl@0: sl@0: User::After(500000); sl@0: sl@0: // Do it once more sl@0: n = 0; sl@0: while (n threadname; sl@0: RThread thread; sl@0: TRequestStatus rs; sl@0: sl@0: // 1. Simple read within buffer sl@0: // Pool 1 sl@0: threadname.Format(KTestThreadRead, 1, 1, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) bufs1[i].Ptr()); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: thread.Close(); sl@0: // Pool 2 sl@0: threadname.Format(KTestThreadRead, 1, 2, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) bufs2[i].Ptr()); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: thread.Close(); sl@0: sl@0: // 2. If the buffer size is not a multiple of the MMU page size, it should be sl@0: // possible to read after the buffer end until the page boundary sl@0: if (*PtrBufSize % pagesize) sl@0: { sl@0: // Pool 1 sl@0: threadname.Format(KTestThreadRead, 2, 1, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) (bufs1[i].Ptr() + pagesize - *PtrBufSize % pagesize)); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: if (rs.Int() != KErrNone) sl@0: { sl@0: test_Equal(KErrUnknown, rs.Int()); sl@0: test_Equal(KErrUnknown, thread.ExitReason()); sl@0: } sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: thread.Close(); sl@0: // Pool 2 sl@0: threadname.Format(KTestThreadRead, 2, 2, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) (bufs2[i].Ptr() + pagesize - *PtrBufSize % pagesize)); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: if (rs.Int() != KErrNone) sl@0: { sl@0: test_Equal(KErrUnknown, rs.Int()); sl@0: test_Equal(KErrUnknown, thread.ExitReason()); sl@0: } sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: thread.Close(); sl@0: } sl@0: sl@0: // 3. Now we attempt to read the first byte on the next page after the end of sl@0: // our buffer. sl@0: TInt offset; sl@0: if (*PtrBufSize % pagesize) sl@0: { sl@0: offset = pagesize - *PtrBufSize % pagesize + 1; sl@0: } sl@0: else sl@0: { sl@0: offset = 1; sl@0: } sl@0: // Pool 1 sl@0: if (bufs1[i + 1].Ptr() == bufs1[i].Ptr() + RoundUp(*PtrBufSize, Log2(pagesize))) sl@0: { sl@0: // Only perform this test if the next buffer comes immediately next to this sl@0: // one. This is not necessarily the case on the Flexible Memory Model. sl@0: threadname.Format(KTestThreadRead, 3, 1, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) (bufs1[i].Ptr() + offset)); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: if (rs.Int() != KErrNone) // No guard page, so it should be fine sl@0: { sl@0: test_Equal(KErrUnknown, rs.Int()); sl@0: test_Equal(KErrUnknown, thread.ExitReason()); sl@0: } sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: thread.Close(); sl@0: } sl@0: // Pool 2 sl@0: TBool jit = User::JustInTime(); sl@0: User::SetJustInTime(EFalse); sl@0: threadname.Format(KTestThreadRead, 3, 2, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) (bufs2[i].Ptr() + offset)); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_Equal(3, rs.Int()); sl@0: test_Equal(EExitPanic, thread.ExitType()); sl@0: test_Equal(3, thread.ExitReason()); // KERN-EXEC 3 sl@0: thread.Close(); sl@0: User::SetJustInTime(jit); sl@0: } sl@0: sl@0: _LIT(KTestThreadWrite, "GuardPagesWriteTS%dP%dB%d"); sl@0: for (i = 0; i < KTestPoolSizeInBufs - 1; i++) sl@0: { sl@0: TBuf<40> threadname; sl@0: RThread thread; sl@0: TRequestStatus rs; sl@0: sl@0: // 1. Simple write within buffer sl@0: // Pool 1 sl@0: threadname.Format(KTestThreadWrite, 1, 1, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesWrite, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) bufs1[i].Ptr()); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: thread.Close(); sl@0: // Pool 2 sl@0: threadname.Format(KTestThreadWrite, 1, 2, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesWrite, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) bufs2[i].Ptr()); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: thread.Close(); sl@0: sl@0: // 2. If the buffer size is not a multiple of the MMU page size, it should be sl@0: // possible to write after the buffer end until the page boundary sl@0: if (*PtrBufSize % pagesize) sl@0: { sl@0: // Pool 1 sl@0: threadname.Format(KTestThreadWrite, 2, 1, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesWrite, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) (bufs1[i].Ptr() + pagesize - *PtrBufSize % pagesize)); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: thread.Close(); sl@0: // Pool 2 sl@0: threadname.Format(KTestThreadWrite, 2, 2, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesWrite, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) (bufs2[i].Ptr() + pagesize - *PtrBufSize % pagesize)); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: thread.Close(); sl@0: } sl@0: sl@0: // 3. Now we attempt to write on the first byte on the next page after the sl@0: // end of our buffer. sl@0: TInt offset; sl@0: if (*PtrBufSize % pagesize) sl@0: { sl@0: offset = pagesize - *PtrBufSize % pagesize + 1; sl@0: } sl@0: else sl@0: { sl@0: offset = 1; sl@0: } sl@0: // Pool 1 sl@0: if (bufs1[i + 1].Ptr() == bufs1[i].Ptr() + RoundUp(*PtrBufSize, Log2(pagesize))) sl@0: { sl@0: // Only perform this test if the next buffer comes immediately next to this sl@0: // one. This is not necessarily the case on the Flexible Memory Model. sl@0: threadname.Format(KTestThreadWrite, 3, 1, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesWrite, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) (bufs1[i].Ptr() + offset)); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_KErrNone(rs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: thread.Close(); sl@0: } sl@0: sl@0: // Pool 2 sl@0: TBool jit = User::JustInTime(); sl@0: User::SetJustInTime(EFalse); sl@0: threadname.Format(KTestThreadWrite, 3, 2, i); sl@0: r = thread.Create(threadname, ThreadGuardPagesWrite, KDefaultStackSize, KMinHeapSize, KMinHeapSize, sl@0: (TAny*) (bufs2[i].Ptr() + offset)); sl@0: test_KErrNone(r); sl@0: thread.Logon(rs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(rs); sl@0: test_Equal(3, rs.Int()); sl@0: test_Equal(EExitPanic, thread.ExitType()); sl@0: test_Equal(3, thread.ExitReason()); // KERN-EXEC 3 sl@0: thread.Close(); sl@0: User::SetJustInTime(jit); sl@0: } sl@0: sl@0: // Free buffers sl@0: for (i = 0; i < KTestPoolSizeInBufs; i++) sl@0: { sl@0: bufs1[i].Close(); sl@0: bufs2[i].Close(); sl@0: } sl@0: pool1.Close(); sl@0: pool2.Close(); sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID 12 sl@0: @SYMTestCaseDesc Buffer mapping sl@0: @SYMREQ REQ11423 sl@0: @SYMTestActions sl@0: 1. Test Thread allocates buffer on a mappable pool. sl@0: 2. Test Thread spawns Slave Process. sl@0: 3. Test Thread passes buffer handle to Slave Process. sl@0: 4. Slave Process attempts to read buffer then write to buffer. sl@0: 5. Slave Process maps buffer. sl@0: 6. Slave Process attempts to read buffer then write to buffer. sl@0: 7. Slave Process unmaps buffer. sl@0: 8. Slave Process attempts to read buffer then write to buffer. sl@0: 9. Test Thread kills Slave Process and frees buffer. sl@0: @SYMTestExpectedResults sl@0: 1. Ok. sl@0: 2. Ok. sl@0: 3. Ok. sl@0: 4. Slave Process panics. (and will have to be restarted) sl@0: 5. Ok. sl@0: 6. Ok. sl@0: 7. Ok. sl@0: 8. Slave Process panics. sl@0: 9. Ok. sl@0: @SYMTestPriority High sl@0: */ sl@0: sl@0: TInt ThreadBufferMappingRead(TAny* aArg) sl@0: { sl@0: if (!aArg) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: RShBuf* buf = (RShBuf*) aArg; sl@0: TUint x = 0; sl@0: TUint i; sl@0: volatile TUint8* ptr = buf->Ptr(); sl@0: sl@0: for (i = 0; i < buf->Size(); i++) sl@0: { sl@0: x += *(ptr + i); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt ThreadBufferMappingWrite(TAny* aArg) sl@0: { sl@0: if (!aArg) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: RShBuf* buf = (RShBuf*) aArg; sl@0: TPtr8 ptr(buf->Ptr(), buf->Size(),buf->Size()); sl@0: ptr.Fill('Q'); sl@0: return KErrNone; sl@0: } sl@0: sl@0: const TInt KTestBufferMappingPoolTypes = 8; sl@0: const TInt KTestBufferMappingTypes = 8; sl@0: sl@0: void BufferMapping() sl@0: { sl@0: test.Next(_L("Buffer Mapping")); sl@0: #ifdef __WINS__ sl@0: test.Printf(_L("Does not run on the emulator. Skipped\n")); sl@0: #else sl@0: TInt r; sl@0: RShPool pool[KTestBufferMappingPoolTypes]; sl@0: RShBuf buf[KTestBufferMappingTypes][KTestBufferMappingPoolTypes]; sl@0: TUint poolflags[KTestBufferMappingPoolTypes]; sl@0: TInt bufferwindow[KTestBufferMappingPoolTypes]; sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize, KTestBufferMappingTypes); sl@0: sl@0: // POOL TYPES sl@0: // ------------------------------------------ sl@0: // Pool no. AutoMap Writeable BufWindow sl@0: // 0 0 0 -1 sl@0: // 1 1 0 -1 sl@0: // 2 0 0 0 sl@0: // 3 1 0 0 sl@0: // 4 0 1 -1 sl@0: // 5 1 1 -1 sl@0: // 6 0 1 0 sl@0: // 7 1 1 0 sl@0: sl@0: TInt i; sl@0: test.Printf(_L("Create pools:")); sl@0: for (i = 0; i < KTestBufferMappingPoolTypes; i++) sl@0: { sl@0: poolflags[i] = EShPoolAllocate; sl@0: bufferwindow[i] = 0; sl@0: if (i % 2) sl@0: { sl@0: poolflags[i] |= EShPoolAutoMapBuf; sl@0: } sl@0: if (i > 3) sl@0: { sl@0: poolflags[i] |= EShPoolWriteable; sl@0: } sl@0: if (i % 4 > 1) sl@0: { sl@0: bufferwindow[i] = -1; sl@0: } sl@0: r = pool[i].Create(inf, poolflags[i] & ~EShPoolAutoMapBuf); sl@0: test_KErrNone(r); sl@0: r = pool[i].SetBufferWindow(bufferwindow[i], poolflags[i] & EShPoolAutoMapBuf); sl@0: test_KErrNone(r); sl@0: test.Printf(_L(".")); sl@0: } sl@0: test.Printf(_L("\n")); sl@0: sl@0: // BUFFER TYPES sl@0: // Buffer no. Actions sl@0: // 0 Alloc unmapped. sl@0: // 1 Alloc unmapped then unmap again. sl@0: // 2 Default Alloc. Unmap if it is a AutoMap pool. sl@0: // 3 Alloc unmapped. Map Read-Only. sl@0: // 4 Default Alloc. Unmap if it is a R/W pool and re-map Read-Only. sl@0: // 5 Alloc unmapped. Map R/W sl@0: // 6 Default Alloc. Unmap and re-map. sl@0: // 7 Default Alloc R/W. Map again with Read-Only setting. sl@0: // Depending on the pool type, the actions above might not always be possible. sl@0: sl@0: // Buffer allocation sl@0: TInt j; sl@0: test.Printf(_L("Allocate buffers\n")); sl@0: for (j = 0; j < KTestBufferMappingPoolTypes; j++) sl@0: { sl@0: test.Printf(_L("\nPool %d:"), j); sl@0: for (i = 0; i < KTestBufferMappingTypes; i++) sl@0: { sl@0: switch (i % KTestBufferMappingTypes) sl@0: { sl@0: // Unmapped buffers sl@0: case 0: sl@0: case 1: sl@0: // This should always result in an unmapped buffer sl@0: r = buf[i][j].Alloc(pool[j], EShPoolAllocNoMap); sl@0: test_KErrNone(r); sl@0: sl@0: if((i % KTestBufferMappingTypes) == 1) sl@0: { sl@0: // Alloc unmapped then unmap again. sl@0: r = buf[i][j].UnMap(); sl@0: test_Equal(KErrNotFound, r); sl@0: } sl@0: break; sl@0: case 2: sl@0: r = buf[i][j].Alloc(pool[j]); sl@0: if (poolflags[j] & EShPoolAutoMapBuf) sl@0: { sl@0: if (bufferwindow[j] == 0) sl@0: { sl@0: // Can't ask for a mapped buffer when buffer window is not set sl@0: test_Equal(KErrNoMemory, r); sl@0: } sl@0: else sl@0: { sl@0: // Alloc'd buffer was mapped - unmap it sl@0: test_KErrNone(r); sl@0: r = buf[i][j].UnMap(); sl@0: test_KErrNone(r); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Buffer not mapped sl@0: test_KErrNone(r); sl@0: } sl@0: break; sl@0: sl@0: // Read-Only buffers sl@0: case 3: sl@0: r = buf[i][j].Alloc(pool[j], EShPoolAllocNoMap); sl@0: test_KErrNone(r); sl@0: r = buf[i][j].Map(ETrue); sl@0: if (bufferwindow[j]) sl@0: { sl@0: test_KErrNone(r); sl@0: } sl@0: else sl@0: { sl@0: test_Equal(KErrNoMemory, r); sl@0: } sl@0: break; sl@0: case 4: sl@0: r = buf[i][j].Alloc(pool[j]); sl@0: if (poolflags[j] & EShPoolAutoMapBuf) sl@0: { sl@0: if (bufferwindow[j] == 0) sl@0: { sl@0: // Can't ask for a mapped buffer when buffer window is not set sl@0: test_Equal(KErrNoMemory, r); sl@0: } sl@0: else if (poolflags[j] & EShPoolWriteable) sl@0: { sl@0: // Alloc'd buffer was mapped R/W - re-map it R/O sl@0: test_KErrNone(r); sl@0: r = buf[i][j].UnMap(); sl@0: test_KErrNone(r); sl@0: r = buf[i][j].Map(ETrue); sl@0: test_KErrNone(r); sl@0: } sl@0: else sl@0: { sl@0: // Nothing to do sl@0: test_KErrNone(r); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Buffer not mapped sl@0: test_KErrNone(r); sl@0: if (bufferwindow[j]) sl@0: { sl@0: if (poolflags[j] & EShPoolWriteable) sl@0: { sl@0: // Explicitly map Read-Only sl@0: r = buf[i][j].Map(ETrue); sl@0: test_KErrNone(r); sl@0: } sl@0: else sl@0: { sl@0: // If Pool is RO, map default sl@0: r = buf[i][j].Map(); sl@0: test_KErrNone(r); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Can't map buffer sl@0: r = buf[i][j].Map(ETrue); sl@0: test_Equal(KErrNoMemory, r); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: // Mapped for Read-Write sl@0: case 5: sl@0: r = buf[i][j].Alloc(pool[j], EShPoolAllocNoMap); sl@0: test_KErrNone(r); sl@0: r = buf[i][j].Map(); sl@0: if (bufferwindow[j] == 0) sl@0: { sl@0: test_Equal(KErrNoMemory, r); sl@0: } sl@0: else if (!(poolflags[j] & EShPoolWriteable)) sl@0: { sl@0: test_KErrNone(r); sl@0: } sl@0: else sl@0: { sl@0: test_KErrNone(r); sl@0: } sl@0: break; sl@0: case 6: sl@0: case 7: sl@0: r = buf[i][j].Alloc(pool[j]); sl@0: if (poolflags[j] & EShPoolAutoMapBuf) sl@0: { sl@0: if (bufferwindow[j] == 0) sl@0: { sl@0: // Can't ask for a mapped buffer when buffer window is not set sl@0: test_Equal(KErrNoMemory, r); sl@0: } sl@0: else if (poolflags[j] & EShPoolWriteable) sl@0: { sl@0: // Alloc'd buffer was mapped R/W sl@0: test_KErrNone(r); sl@0: sl@0: if((i % KTestBufferMappingTypes) == 7) sl@0: { sl@0: // Mapped for Read-Write then remapped as Read-Only sl@0: r = buf[i][j].Map(true); sl@0: test_Equal(KErrAlreadyExists, r); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Buffer not mapped sl@0: test_KErrNone(r); sl@0: if (bufferwindow[j]) sl@0: { sl@0: if (poolflags[j] & EShPoolWriteable) sl@0: { sl@0: // Default mapping sl@0: r = buf[i][j].Map(); sl@0: test_KErrNone(r); sl@0: sl@0: if((i % KTestBufferMappingTypes) == 7) sl@0: { sl@0: // Mapped for Read-Write then remapped as Read-Only sl@0: r = buf[i][j].Map(true); sl@0: test_Equal(KErrAlreadyExists, r); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Can't map buffer sl@0: r = buf[i][j].Map(ETrue); sl@0: test_Equal(KErrNoMemory, r); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: default: test(EFalse); sl@0: } sl@0: test.Printf(_L(".")); sl@0: } sl@0: } sl@0: test.Printf(_L("\n")); sl@0: sl@0: // Read and write tests sl@0: _LIT(KTestThreadName, "BufferMappingBuf%d(Test%d)"); sl@0: test.Printf(_L("Read & Write tests\n")); sl@0: for (j = 0; j < KTestBufferMappingPoolTypes; j++) sl@0: { sl@0: for (i = 0; i < KTestBufferMappingTypes; i++) sl@0: { sl@0: if (buf[i][j].Handle()) sl@0: { sl@0: switch (i % KTestBufferMappingTypes) sl@0: { sl@0: case 1: sl@0: case 2: sl@0: // Buffer not mapped - Read should fail sl@0: if (buf[i][j].Ptr() == NULL) sl@0: { sl@0: RThread thread; sl@0: TRequestStatus threadrs; sl@0: TBuf<40> threadname; sl@0: threadname.Format(KTestThreadName, i, (i % KTestBufferMappingTypes) + 1); sl@0: r = thread.Create(threadname, ThreadBufferMappingRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize, (TAny*) &buf[i][j]); sl@0: test_KErrNone(r); sl@0: thread.Logon(threadrs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(threadrs); sl@0: test_Equal(3, threadrs.Int()); sl@0: test_Equal(EExitPanic, thread.ExitType()); sl@0: test_Equal(3, thread.ExitReason()); // KERN-EXEC 3 sl@0: CLOSE_AND_WAIT(thread); sl@0: // Map buffer read-only for next test sl@0: r = buf[i][j].Map(ETrue); sl@0: if (bufferwindow[j]) sl@0: { sl@0: test_KErrNone(r); sl@0: } sl@0: else sl@0: { sl@0: test_Equal(KErrNoMemory, r); sl@0: } sl@0: } sl@0: case 3: sl@0: case 4: sl@0: // Buffer mapped for R/O access - Read should not fail sl@0: if (bufferwindow[j] == 0) sl@0: { sl@0: break; sl@0: } sl@0: else sl@0: { sl@0: RThread thread; sl@0: TRequestStatus threadrs; sl@0: TBuf<40> threadname; sl@0: threadname.Format(KTestThreadName, i, (i % KTestBufferMappingTypes) + 1); sl@0: r = thread.Create(threadname, ThreadBufferMappingRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize, (TAny*) &buf[i][j]); sl@0: test_KErrNone(r); sl@0: thread.Logon(threadrs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(threadrs); sl@0: test_KErrNone(threadrs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: CLOSE_AND_WAIT(thread); sl@0: } sl@0: // Write should fail sl@0: if (buf[i][j].Ptr()) sl@0: { sl@0: RThread thread; sl@0: TRequestStatus threadrs; sl@0: TBuf<40> threadname; sl@0: threadname.Format(KTestThreadName, i, (i % KTestBufferMappingTypes) + 2); sl@0: r = thread.Create(threadname, ThreadBufferMappingWrite, KDefaultStackSize, KMinHeapSize, KMinHeapSize,(TAny*) &buf[i][j]); sl@0: test_KErrNone(r); sl@0: thread.Logon(threadrs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(threadrs); sl@0: test_Equal(3, threadrs.Int()); sl@0: test_Equal(EExitPanic, thread.ExitType()); sl@0: test_Equal(3, thread.ExitReason()); // KERN-EXEC 3 sl@0: CLOSE_AND_WAIT(thread); sl@0: // Map buffer read-write for next test sl@0: r = buf[i][j].UnMap(); sl@0: if(r != KErrNotFound) sl@0: { sl@0: test_KErrNone(r); sl@0: } sl@0: r = buf[i][j].Map(); sl@0: test_KErrNone(r); sl@0: } sl@0: case 5: sl@0: case 6: sl@0: // Buffer mapped for R/W access - Write should not fail sl@0: if (bufferwindow[j] == 0 || !(poolflags[j] & EShPoolWriteable)) sl@0: { sl@0: break; sl@0: } sl@0: else sl@0: { sl@0: RThread thread; sl@0: TRequestStatus threadrs; sl@0: TBuf<40> threadname; sl@0: threadname.Format(KTestThreadName, i, (i % KTestBufferMappingTypes) + 1); sl@0: r = thread.Create(threadname, ThreadBufferMappingWrite, KDefaultStackSize, KMinHeapSize, KMinHeapSize,(TAny*) &buf[i][j]); sl@0: test_KErrNone(r); sl@0: thread.Logon(threadrs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(threadrs); sl@0: test_KErrNone(threadrs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: CLOSE_AND_WAIT(thread); sl@0: // Unmap buffer for next test sl@0: r = buf[i][j].UnMap(); sl@0: test_KErrNone(r); sl@0: } sl@0: // Buffer not mapped - Read should fail sl@0: if (buf[i][j].Ptr()) sl@0: { sl@0: RThread thread; sl@0: TRequestStatus threadrs; sl@0: TBuf<40> threadname; sl@0: threadname.Format(KTestThreadName, i, (i % KTestBufferMappingTypes) + 2); sl@0: r = thread.Create(threadname, ThreadBufferMappingRead, KDefaultStackSize, KMinHeapSize, KMinHeapSize,(TAny*) &buf[i][j]); sl@0: test_KErrNone(r); sl@0: thread.Logon(threadrs); sl@0: thread.Resume(); sl@0: User::WaitForRequest(threadrs); sl@0: test_Equal(3, threadrs.Int()); sl@0: test_Equal(EExitPanic, thread.ExitType()); sl@0: test_Equal(3, thread.ExitReason()); // KERN-EXEC 3 sl@0: CLOSE_AND_WAIT(thread); sl@0: } sl@0: } sl@0: } sl@0: buf[i][j].Close(); sl@0: test.Printf(_L(".")); sl@0: } sl@0: pool[j].Close(); sl@0: test.Printf(_L("\n")); sl@0: } sl@0: #endif sl@0: } sl@0: sl@0: void BufferWindow() sl@0: { sl@0: test.Next(_L("Buffer Window tests")); sl@0: #ifdef __WINS__ sl@0: test.Printf(_L("Does not run on the emulator. Skipped\n")); sl@0: #else sl@0: TInt r; sl@0: RShPool pool; sl@0: RShBuf buf[KTestPoolSizeInBufs * 2 + 1]; sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize, KTestPoolSizeInBufs * 2); sl@0: r = pool.Create(inf, KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: sl@0: // Allocate buffer but don't map them to this process memory sl@0: TInt i; sl@0: for (i = 0; i < KTestPoolSizeInBufs * 2; i++) sl@0: { sl@0: r = buf[i].Alloc(pool, EShPoolAllocNoMap); sl@0: test_KErrNone(r); sl@0: } sl@0: sl@0: // Pool is full sl@0: r = buf[KTestPoolSizeInBufs * 2].Alloc(pool, EShPoolAllocNoMap); sl@0: test_Equal(KErrNoMemory, r); sl@0: r = buf[0].Map(); sl@0: test_Equal(KErrNoMemory, r); sl@0: sl@0: // Open a one-buffer window sl@0: r = pool.SetBufferWindow(1, ETrue); sl@0: test_KErrNone(r); sl@0: r = buf[0].Map(); sl@0: test_KErrNone(r); sl@0: TPtr8 ptr0(buf[0].Ptr(), buf[0].Size(),buf[0].Size()); sl@0: ptr0.Fill('>'); sl@0: r = buf[1].Map(); sl@0: test_Equal(KErrNoMemory, r); sl@0: r = buf[0].UnMap(); sl@0: test_KErrNone(r); sl@0: r = buf[1].Map(); sl@0: test_KErrNone(r); sl@0: TPtr8 ptr1(buf[0].Ptr(), buf[0].Size(),buf[0].Size()); sl@0: ptr1.Fill('<'); sl@0: r = buf[2].Map(); sl@0: test_Equal(KErrNoMemory, r); sl@0: sl@0: // Enlarge window by one buffer sl@0: r = pool.SetBufferWindow(2, ETrue); sl@0: test_Equal(KErrAlreadyExists, r); sl@0: sl@0: // Close All buffers sl@0: for (i = 0; i < KTestPoolSizeInBufs * 2; i++) sl@0: { sl@0: buf[i].Close(); sl@0: } sl@0: sl@0: pool.Close(); sl@0: r = pool.Create(inf, KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: sl@0: r = pool.SetBufferWindow(KTestPoolSizeInBufs, ETrue); // Half the pool size sl@0: test_KErrNone(r); sl@0: for (i = 0; i < KTestPoolSizeInBufs * 2 - 1; i++) sl@0: { sl@0: if (i < KTestPoolSizeInBufs) sl@0: { sl@0: r = buf[i].Alloc(pool, 0); sl@0: test_KErrNone(r); sl@0: TPtr8 ptr(buf[0].Ptr(), buf[0].Size(),buf[0].Size()); sl@0: ptr.Fill('?'); sl@0: } sl@0: else sl@0: { sl@0: r = buf[i].Alloc(pool, EShPoolAllocNoMap); sl@0: test_KErrNone(r); sl@0: } sl@0: } sl@0: r = buf[KTestPoolSizeInBufs * 2].Alloc(pool, 0); sl@0: test_Equal(KErrNoMemory, r); sl@0: r = buf[KTestPoolSizeInBufs].Map(); sl@0: test_Equal(KErrNoMemory, r); sl@0: r = buf[KTestPoolSizeInBufs * 2].Alloc(pool, EShPoolAllocNoMap); sl@0: test_KErrNone(r); sl@0: sl@0: // That's it sl@0: for (i = 0; i < (KTestPoolSizeInBufs * 2) + 1; i++) sl@0: { sl@0: buf[i].Close(); sl@0: } sl@0: pool.Close(); sl@0: sl@0: // Try again with automap set to false sl@0: RShPool pool2; sl@0: r = pool2.Create(inf, KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: for (i = 0; i < KTestPoolSizeInBufs * 2; i++) sl@0: { sl@0: r = buf[i].Alloc(pool2, 0); sl@0: test_KErrNone(r); sl@0: } sl@0: r = pool2.SetBufferWindow(-1, EFalse); sl@0: test_KErrNone(r); sl@0: for (i = 0; i < KTestPoolSizeInBufs * 2; i++) sl@0: { sl@0: r = buf[i].Map(ETrue); sl@0: test_KErrNone(r); sl@0: } sl@0: for (i = 0; i < KTestPoolSizeInBufs * 2; i++) sl@0: { sl@0: buf[i].Close(); sl@0: } sl@0: pool2.Close(); sl@0: #endif sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID 7 sl@0: @SYMTestCaseDesc Trigger notifications sl@0: @SYMREQ REQ11423 sl@0: @SYMTestActions sl@0: Set Low Space Notifications on various thresholds. sl@0: In a separate thread, keep allocating buffers. sl@0: @SYMTestExpectedResults sl@0: Notifications are completed when their respective levels are reached. sl@0: @SYMTestPriority Medium sl@0: */ sl@0: sl@0: TInt ThreadNotifications(TAny* aArg) sl@0: { sl@0: if (!aArg) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: RShPool* pool = (RShPool*) aArg; sl@0: RArray bufarray; sl@0: TInt r; sl@0: RSemaphore sem; sl@0: r = sem.OpenGlobal(KTestLowSpaceSemaphore); sl@0: if (r) sl@0: { sl@0: RDebug::Printf("Line %d: r=%d", __LINE__, r); sl@0: return r; sl@0: } sl@0: // Start allocating buffers sl@0: while (pool->FreeCount() > 1) sl@0: { sl@0: RShBuf buf; sl@0: r = buf.Alloc(*pool); sl@0: if (r) sl@0: { sl@0: RDebug::Printf("Line %d: count=%d r=%d", __LINE__, bufarray.Count(), r); sl@0: return r; sl@0: } sl@0: bufarray.Append(buf); sl@0: if ((bufarray.Count() == 1) // wait for low3 sl@0: || (bufarray.Count() == KTestPoolSizeInBufs - 2) // wait for low2 sl@0: || (bufarray.Count() == KTestPoolSizeInBufs - 1)) // wait for low1/low4 sl@0: { sl@0: r = sem.Wait(5000000); // 5 second timeout sl@0: if (r) sl@0: { sl@0: RDebug::Printf("Line %d: count=%d r=%d", __LINE__, bufarray.Count(), r); sl@0: return r; sl@0: } sl@0: } sl@0: } sl@0: sl@0: // Free all buffers sl@0: while (bufarray.Count()) sl@0: { sl@0: bufarray[0].Close(); sl@0: bufarray.Remove(0); sl@0: if ((bufarray.Count() == KTestPoolSizeInBufs - 2) // wait for free3 sl@0: || (bufarray.Count() == 1) // wait for free2 sl@0: || (bufarray.Count() == 0)) // wait for free1/free4 sl@0: { sl@0: r = sem.Wait(5000000); // 5 second timeout sl@0: if (r) sl@0: { sl@0: RDebug::Printf("Line %d: count=%d r=%d", __LINE__, bufarray.Count(), r); sl@0: return r; sl@0: } sl@0: } sl@0: } sl@0: bufarray.Close(); sl@0: sem.Close(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: enum TTestLowSpaceType sl@0: { sl@0: ETestCancelNonExistent, sl@0: ETestCancelTwice sl@0: }; sl@0: sl@0: struct TTestThreadLowSpacePanicArgs sl@0: { sl@0: RShPool* iPool; sl@0: TUint iThreshold1; sl@0: TUint iThreshold2; sl@0: TTestLowSpaceType iType; sl@0: }; sl@0: sl@0: TInt ThreadLowSpacePanic(TAny* aArg) sl@0: { sl@0: if (!aArg) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: TTestThreadLowSpacePanicArgs& targs = *(TTestThreadLowSpacePanicArgs*) aArg; sl@0: TRequestStatus rs; sl@0: if (targs.iType == ETestCancelNonExistent) sl@0: { sl@0: targs.iPool->CancelLowSpaceNotification(rs); // should panic sl@0: } sl@0: else if (targs.iType == ETestCancelTwice) sl@0: { sl@0: targs.iPool->RequestLowSpaceNotification(targs.iThreshold1, rs); sl@0: targs.iPool->CancelLowSpaceNotification(rs); sl@0: targs.iPool->CancelLowSpaceNotification(rs); // should panic sl@0: } sl@0: else sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: /* sl@0: * CancelLowSpaceNotification() no longer panic()s if it can't find the sl@0: * notification, so this routine not currently called. sl@0: */ sl@0: void RequestLowSpacePanic(RShPool& aPool, TUint aThreshold1, TUint aThreshold2, TTestLowSpaceType aType, TInt aLine) sl@0: { sl@0: static TInt count = 0; sl@0: count++; sl@0: test.Printf(_L("RequestLowSpacePanic@%d(%d)\n"), aLine, count); sl@0: TBool jit = User::JustInTime(); sl@0: User::SetJustInTime(EFalse); sl@0: TInt expectedpaniccode = KErrNone; // Initialised to silence compiler warnings sl@0: switch (aType) sl@0: { sl@0: case ETestCancelNonExistent: sl@0: case ETestCancelTwice: sl@0: expectedpaniccode = KErrNotFound; sl@0: break; sl@0: default: sl@0: test(EFalse); sl@0: } sl@0: // sl@0: TTestThreadLowSpacePanicArgs targs; sl@0: targs.iPool = &aPool; sl@0: targs.iThreshold1 = aThreshold1; sl@0: targs.iThreshold2 = aThreshold2; sl@0: targs.iType = aType; sl@0: // sl@0: RThread threadpanic; sl@0: TRequestStatus threadpanicrs; sl@0: TInt r; sl@0: TBuf<30> threadname; sl@0: threadname.Format(_L("ThreadLowSpacePanic%d"), count); sl@0: r = threadpanic.Create(threadname, ThreadLowSpacePanic, KDefaultStackSize, KMinHeapSize, 1 << 20, (TAny*) &targs); sl@0: test_KErrNone(r); sl@0: threadpanic.Logon(threadpanicrs); sl@0: threadpanic.Resume(); sl@0: User::WaitForRequest(threadpanicrs); sl@0: // sl@0: test_Equal(expectedpaniccode, threadpanicrs.Int()); sl@0: test_Equal(EExitPanic, threadpanic.ExitType()); sl@0: test_Equal(expectedpaniccode, threadpanic.ExitReason()); sl@0: threadpanic.Close(); sl@0: User::SetJustInTime(jit); sl@0: } sl@0: sl@0: void NotificationRequests(RShPool& aPool) sl@0: { sl@0: test.Next(_L("Notifications")); sl@0: TInt r; sl@0: sl@0: RSemaphore sem; sl@0: r = sem.CreateGlobal(KTestLowSpaceSemaphore, 0); sl@0: test_KErrNone(r); sl@0: RTimer timer; sl@0: r = timer.CreateLocal(); sl@0: test_KErrNone(r); sl@0: RThread thread; sl@0: TRequestStatus threadrs; sl@0: r = thread.Create(_L("ThreadNotifications"), ThreadNotifications, KDefaultStackSize, KMinHeapSize, 1 << 20, (TAny*) &aPool); sl@0: test_KErrNone(r); sl@0: thread.SetPriority(EPriorityMore); sl@0: thread.Logon(threadrs); sl@0: sl@0: test.Printf(_L("Low space notification\n")); sl@0: TRequestStatus low1; sl@0: TRequestStatus low2; sl@0: TRequestStatus low3; sl@0: TRequestStatus low4; sl@0: TRequestStatus low5; sl@0: TRequestStatus low6; sl@0: aPool.RequestLowSpaceNotification(1, low1); sl@0: test_Equal(KRequestPending, low1.Int()); sl@0: aPool.RequestLowSpaceNotification(2, low2); sl@0: test_Equal(KRequestPending, low2.Int()); sl@0: aPool.RequestLowSpaceNotification(aPool.FreeCount() - 1, low3); sl@0: test_Equal(KRequestPending, low3.Int()); sl@0: aPool.RequestLowSpaceNotification(1, low4); sl@0: test_Equal(KRequestPending, low4.Int()); sl@0: aPool.RequestLowSpaceNotification(0, low5); // Never completes sl@0: test_Equal(KRequestPending, low5.Int()); sl@0: aPool.RequestLowSpaceNotification(KMaxTUint, low6); // Completes instantly sl@0: TRequestStatus timeoutlow; sl@0: timer.After(timeoutlow, 5000000); // 5 seconds time out sl@0: User::WaitForRequest(low6, timeoutlow); sl@0: test_KErrNone(low6.Int()); sl@0: test_Equal(KRequestPending, low1.Int()); sl@0: test_Equal(KRequestPending, low2.Int()); sl@0: test_Equal(KRequestPending, low3.Int()); sl@0: test_Equal(KRequestPending, low4.Int()); sl@0: test_Equal(KRequestPending, low5.Int()); sl@0: timer.Cancel(); sl@0: User::WaitForRequest(timeoutlow); sl@0: thread.Resume(); sl@0: User::WaitForRequest(low3, threadrs); sl@0: test_KErrNone(low3.Int()); sl@0: test_Equal(KRequestPending, low1.Int()); sl@0: test_Equal(KRequestPending, low2.Int()); sl@0: test_Equal(KRequestPending, low4.Int()); sl@0: test_Equal(KRequestPending, low5.Int()); sl@0: sem.Signal(); sl@0: User::WaitForRequest(low2, threadrs); sl@0: test_KErrNone(low2.Int()) sl@0: test_Equal(KRequestPending, low1.Int()); sl@0: test_Equal(KRequestPending, low4.Int()); sl@0: test_Equal(KRequestPending, low5.Int()); sl@0: sem.Signal(); sl@0: User::WaitForRequest(low1, threadrs); sl@0: test_KErrNone(low1.Int()); sl@0: User::WaitForRequest(low4, threadrs); sl@0: test_KErrNone(low4.Int()); sl@0: test_Equal(KRequestPending, low5.Int()); sl@0: test_Equal(EExitPending, thread.ExitType()); // Thread is still running sl@0: test_Compare(aPool.FreeCount(), <=, 1); sl@0: sl@0: test.Printf(_L("Free space notification\n")); sl@0: TRequestStatus free1; sl@0: TRequestStatus free2; sl@0: TRequestStatus free3; sl@0: TRequestStatus free4; sl@0: TRequestStatus free5; sl@0: TRequestStatus free6; sl@0: aPool.RequestFreeSpaceNotification(KTestPoolSizeInBufs, free1); sl@0: test_Equal(KRequestPending, free1.Int()); sl@0: aPool.RequestFreeSpaceNotification(KTestPoolSizeInBufs - 1, free2); sl@0: test_Equal(KRequestPending, free2.Int()); sl@0: aPool.RequestFreeSpaceNotification(aPool.FreeCount() + 1, free3); sl@0: test_Equal(KRequestPending, free3.Int()); sl@0: aPool.RequestFreeSpaceNotification(KTestPoolSizeInBufs, free4); sl@0: test_Equal(KRequestPending, free4.Int()); sl@0: aPool.RequestFreeSpaceNotification(KTestPoolSizeInBufs + 1, free5); // Never completes sl@0: test_Equal(KRequestPending, free5.Int()); sl@0: aPool.RequestFreeSpaceNotification(0, free6); // Completes instantly sl@0: sl@0: TRequestStatus timeoutfree; sl@0: timer.After(timeoutfree, 5000000); // 5 seconds time out sl@0: User::WaitForRequest(free6, timeoutfree); sl@0: test_KErrNone(free6.Int()); sl@0: sl@0: test_Equal(KRequestPending, free1.Int()); sl@0: test_Equal(KRequestPending, free2.Int()); sl@0: test_Equal(KRequestPending, free3.Int()); sl@0: test_Equal(KRequestPending, free4.Int()); sl@0: test_Equal(KRequestPending, free5.Int()); sl@0: sl@0: timer.Cancel(); sl@0: User::WaitForRequest(timeoutfree); sl@0: sl@0: sem.Signal(); // resume thread execution sl@0: User::WaitForRequest(free3, threadrs); sl@0: test_KErrNone(free3.Int()); sl@0: test_Equal(KRequestPending, free1.Int()); sl@0: test_Equal(KRequestPending, free2.Int()); sl@0: test_Equal(KRequestPending, free4.Int()); sl@0: test_Equal(KRequestPending, free5.Int()); sl@0: sl@0: sem.Signal(); sl@0: User::WaitForRequest(free2, threadrs); sl@0: test_KErrNone(free2.Int()) sl@0: sl@0: test_Equal(KRequestPending, free1.Int()); sl@0: test_Equal(KRequestPending, free4.Int()); sl@0: test_Equal(KRequestPending, free5.Int()); sl@0: sem.Signal(); sl@0: sl@0: User::WaitForRequest(free1, threadrs); sl@0: test_KErrNone(free1.Int()); sl@0: test_KErrNone(free4.Int()); sl@0: sl@0: test_Equal(KRequestPending, free5.Int()); sl@0: test_Equal(EExitPending, thread.ExitType()); // Thread is still running sl@0: sl@0: test_Compare(aPool.FreeCount(), >=, KTestPoolSizeInBufs); sl@0: sl@0: // Complete the requests still pending... sl@0: aPool.CancelLowSpaceNotification(low5); sl@0: User::WaitForRequest(low5); sl@0: sl@0: aPool.CancelFreeSpaceNotification(free5); sl@0: User::WaitForRequest(free5); sl@0: sl@0: // Let thread complete sl@0: sem.Signal(); sl@0: User::WaitForRequest(threadrs); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: thread.Close(); sl@0: sem.Close(); sl@0: timer.Close(); sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID 9 sl@0: @SYMTestCaseDesc Cancel low- and free-space notifications sl@0: @SYMREQ REQ11423 sl@0: @SYMTestActions sl@0: Set Low/High LowSpace Notifications. sl@0: Cancel them. sl@0: @SYMTestExpectedResults sl@0: All OK. sl@0: @SYMTestPriority Medium sl@0: */ sl@0: sl@0: void CancelNotificationRequests(RShPool& aPool) sl@0: { sl@0: test.Next(_L("Cancel notifications")); sl@0: TInt r; sl@0: sl@0: RSemaphore sem; sl@0: r = sem.CreateGlobal(KTestLowSpaceSemaphore, 0); sl@0: test_KErrNone(r); sl@0: RThread thread; sl@0: TRequestStatus threadrs; sl@0: r = thread.Create(_L("ThreadCancelNotifications"), ThreadNotifications, KDefaultStackSize, KMinHeapSize, 1 << 20, (TAny*) &aPool); sl@0: test_KErrNone(r); sl@0: thread.SetPriority(EPriorityLess); sl@0: thread.Logon(threadrs); sl@0: sl@0: test.Printf(_L("Cancel low space notifications\n")); sl@0: // Low space notification cancel sl@0: TRequestStatus low; sl@0: aPool.RequestLowSpaceNotification(1, low); sl@0: aPool.CancelLowSpaceNotification(low); sl@0: test_Equal(KErrCancel, low.Int()); sl@0: // We should be able to cancel again without panic()ing sl@0: // (no guarantees on return code; maybe Cancel() should have void return type?) sl@0: aPool.CancelLowSpaceNotification(low); sl@0: test.Printf(_L("Second cancel returned %d\n"), low.Int()); sl@0: TRequestStatus low2; sl@0: aPool.RequestLowSpaceNotification(1, low2); // For thread sync sl@0: thread.Resume(); sl@0: sem.Signal(2); sl@0: User::WaitForRequest(low2, threadrs); sl@0: test_KErrNone(low2.Int()); sl@0: test_Equal(EExitPending, thread.ExitType()); // Thread is still running sl@0: test_Compare(aPool.FreeCount(), <=, 1); sl@0: sl@0: test.Printf(_L("Cancel free space notifications\n")); sl@0: TRequestStatus free; sl@0: aPool.CancelFreeSpaceNotification(free); // Cancel non-existant notification sl@0: aPool.RequestFreeSpaceNotification(KTestPoolSizeInBufs, free); sl@0: aPool.CancelLowSpaceNotification(free); // Use wrong method sl@0: aPool.CancelFreeSpaceNotification(free); // Use wrong method sl@0: test_Equal(KErrCancel, free.Int()); sl@0: aPool.CancelFreeSpaceNotification(free); // Already cancelled sl@0: sl@0: // Complete the requests still pending... sl@0: User::WaitForRequest(low); sl@0: sl@0: sem.Signal(4); // Resume thread execution and let it complete sl@0: User::WaitForRequest(threadrs); sl@0: test_KErrNone(threadrs.Int()); sl@0: test_Equal(EExitKill, thread.ExitType()); sl@0: test_KErrNone(thread.ExitReason()); sl@0: test_Compare(aPool.FreeCount(), >=, KTestPoolSizeInBufs); sl@0: thread.Close(); sl@0: sem.Close(); sl@0: } sl@0: sl@0: sl@0: /* sl@0: @SYMTestCaseID 10 sl@0: @SYMTestCaseDesc Grow and shrink pool sl@0: @SYMREQ REQ11423 sl@0: @SYMTestActions sl@0: 1. Test Thread creates pools with various size attributes sl@0: 2. Test Thread keeps allocating buffers on pool. sl@0: 3. Test Thread keeps freeing buffers on pool sl@0: 4. Test Thread frees all buffers and close pool. sl@0: @SYMTestExpectedResults sl@0: Pools grows and shrink grows as expected. sl@0: @SYMTestPriority High sl@0: */ sl@0: sl@0: const TInt KTestFreeCountTimeOut = 20000000; // 20 seconds (of thread inactivity) sl@0: const TInt KTestWaitBeforeRetry = 2000; // 0.002 second sl@0: sl@0: TUint MultFx248(TUint n, TUint f) sl@0: { sl@0: TUint64 r = (TUint64) n * f; sl@0: I64LSR(r, 8); sl@0: return r > KMaxTUint32 ? KMaxTUint32 : I64LOW(r); sl@0: } sl@0: sl@0: class TTestPoolModel sl@0: { sl@0: public: sl@0: TTestPoolModel(TShPoolInfo& aInfo); sl@0: void Alloc(); sl@0: void Free(); sl@0: TUint FreeCount(); sl@0: void DisplayCounters(); sl@0: private: sl@0: void CalcGSP(); sl@0: void CheckGrowShrink(); sl@0: void Grow(); sl@0: void Shrink(); sl@0: private: sl@0: TUint iAllocated; sl@0: TUint iFree; sl@0: // sl@0: TUint iInitial; sl@0: TUint iMax; sl@0: TUint iGrowTriggerRatio; sl@0: TUint iGrowByRatio; sl@0: TUint iShrinkByRatio; sl@0: TUint iShrinkHysteresisRatio; sl@0: TUint iPoolFlags; sl@0: // sl@0: TUint iGrowTrigger; sl@0: TUint iShrinkTrigger; sl@0: // sl@0: TBool iDebug; sl@0: }; sl@0: sl@0: TTestPoolModel::TTestPoolModel(TShPoolInfo& aInfo) sl@0: { sl@0: iInitial = aInfo.iInitialBufs; sl@0: iMax = aInfo.iMaxBufs; sl@0: iGrowTriggerRatio = aInfo.iGrowTriggerRatio; sl@0: iGrowByRatio = aInfo.iGrowByRatio; sl@0: iShrinkByRatio = 256 - 65536 / (256 + iGrowByRatio); sl@0: iShrinkHysteresisRatio = aInfo.iShrinkHysteresisRatio; sl@0: iPoolFlags = aInfo.iFlags; sl@0: iAllocated = 0; sl@0: iFree = iInitial; sl@0: iDebug = EFalse; // Set this to ETrue to display detailed information sl@0: sl@0: CalcGSP(); sl@0: if (iDebug) sl@0: { sl@0: test.Printf(_L("A F A+F GT ST \n")); sl@0: test.Printf(_L("==============================\n")); sl@0: DisplayCounters(); sl@0: } sl@0: } sl@0: sl@0: void TTestPoolModel::Alloc() sl@0: { sl@0: iAllocated++; sl@0: iFree--; sl@0: CheckGrowShrink(); sl@0: } sl@0: sl@0: void TTestPoolModel::Free() sl@0: { sl@0: iAllocated--; sl@0: iFree++; sl@0: CheckGrowShrink(); sl@0: } sl@0: sl@0: TUint TTestPoolModel::FreeCount() sl@0: { sl@0: return iFree; sl@0: } sl@0: sl@0: void TTestPoolModel::CalcGSP() sl@0: { sl@0: TUint n = iAllocated + iFree; sl@0: sl@0: // If the pool is at its maximum size, we can't grow sl@0: if (n >= iMax || iGrowTriggerRatio == 0 /*|| iCommittedPages >= iMaxPages*/) sl@0: { sl@0: iGrowTrigger = 0; sl@0: } sl@0: else sl@0: { sl@0: iGrowTrigger = MultFx248(n, iGrowTriggerRatio); sl@0: sl@0: // Deal with rounding towards zero sl@0: if (iGrowTrigger == 0) sl@0: iGrowTrigger = 1; sl@0: } sl@0: sl@0: // If no growing has happened, we can't shrink sl@0: if (n <= iInitial || iGrowTriggerRatio == 0 || (iPoolFlags & EShPoolSuppressShrink) != 0) sl@0: { sl@0: iShrinkTrigger = iMax; sl@0: } sl@0: else sl@0: { sl@0: // To ensure that shrinking doesn't immediately happen after growing, the trigger sl@0: // amount is the grow trigger + the grow amount (which is the number of free buffers sl@0: // just after a grow) times the shrink hysteresis value. sl@0: iShrinkTrigger = MultFx248(n, iGrowTriggerRatio + iGrowByRatio); sl@0: iShrinkTrigger = MultFx248(iShrinkTrigger, iShrinkHysteresisRatio); sl@0: sl@0: // Deal with rounding towards zero sl@0: if (iShrinkTrigger == 0) sl@0: iShrinkTrigger = 1; sl@0: sl@0: // If the shrink trigger ends up > the number of buffers currently in sl@0: // the pool, set it to that number (less 1, since the test is "> trigger"). sl@0: // This means the pool will only shrink when all the buffers have been freed. sl@0: if (iShrinkTrigger >= n) sl@0: iShrinkTrigger = n - 1; sl@0: } sl@0: if (iDebug) sl@0: { sl@0: DisplayCounters(); sl@0: } sl@0: } sl@0: sl@0: void TTestPoolModel::CheckGrowShrink() sl@0: { sl@0: if (iFree < iGrowTrigger) sl@0: { sl@0: Grow(); sl@0: CheckGrowShrink(); sl@0: } sl@0: if (iFree > iShrinkTrigger) sl@0: { sl@0: Shrink(); sl@0: CheckGrowShrink(); sl@0: } sl@0: } sl@0: sl@0: void TTestPoolModel::Grow() sl@0: { sl@0: TUint headroom = iMax - (iAllocated + iFree); sl@0: TUint growby = MultFx248(iAllocated + iFree, iGrowByRatio); sl@0: if (growby == 0) // Handle round-to-zero sl@0: growby = 1; sl@0: if (growby > headroom) sl@0: growby = headroom; sl@0: iFree += growby; sl@0: if (iDebug) sl@0: { sl@0: test.Printf(_L("GROW by %d!\n"), growby); sl@0: } sl@0: CalcGSP(); sl@0: } sl@0: sl@0: void TTestPoolModel::Shrink() sl@0: { sl@0: TUint grownBy = iAllocated + iFree - iInitial; sl@0: TUint shrinkby = MultFx248(iAllocated + iFree, iShrinkByRatio); sl@0: if (shrinkby == 0) // Handle round-to-zero sl@0: shrinkby = 1; sl@0: if (shrinkby > grownBy) sl@0: shrinkby = grownBy; sl@0: if (shrinkby > iFree) sl@0: shrinkby = iFree; sl@0: iFree -= shrinkby; sl@0: if (iDebug) sl@0: { sl@0: test.Printf(_L("SHRINK by %d!\n"), shrinkby); sl@0: } sl@0: CalcGSP(); sl@0: } sl@0: sl@0: void TTestPoolModel::DisplayCounters() sl@0: { sl@0: test.Printf(_L("%-6u%-6u%-6u%-6u%-6u\n"), iAllocated, iFree, iAllocated + iFree, iGrowTrigger, iShrinkTrigger); sl@0: } sl@0: sl@0: void PoolGrowingTestRoutine(const TShPoolCreateInfo& aInfo, TUint aBufferFlags = 0) sl@0: { sl@0: TInt r; sl@0: TInt timeout; sl@0: RShPool pool; sl@0: r = pool.Create(aInfo, KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: sl@0: TShPoolInfo info; sl@0: pool.GetInfo(info); sl@0: sl@0: // Only set the buffer window if we're going to map the buffers sl@0: if (!(aBufferFlags & EShPoolAllocNoMap) && (info.iFlags & EShPoolPageAlignedBuffer)) sl@0: { sl@0: r = pool.SetBufferWindow(-1, ETrue); sl@0: test_KErrNone(r) sl@0: } sl@0: sl@0: TTestPoolModel model(info); sl@0: RArray bufarray; sl@0: test_Equal(info.iInitialBufs, pool.FreeCount()); sl@0: sl@0: // Buffer allocation sl@0: do sl@0: { sl@0: timeout = KTestFreeCountTimeOut / KTestWaitBeforeRetry; sl@0: while (model.FreeCount() != pool.FreeCount()) sl@0: { sl@0: User::After(KTestWaitBeforeRetry); sl@0: test_Assert(--timeout, sl@0: test.Printf(_L("Timeout: Free==%u (expected %u)\n"), pool.FreeCount(), model.FreeCount()); sl@0: model.DisplayCounters(); sl@0: ); sl@0: if ((timeout * KTestWaitBeforeRetry) % 1000000 == 0) sl@0: { sl@0: test.Printf(_L("Time out in %d seconds! (line %d)\n"), timeout * KTestWaitBeforeRetry / 1000000, __LINE__); sl@0: } sl@0: } sl@0: RShBuf buf; sl@0: r = buf.Alloc(pool, aBufferFlags); sl@0: if (r == KErrNoMemory) sl@0: { sl@0: // We expect to get a failure when all buffers are allocated sl@0: if ((TUint) bufarray.Count() == info.iMaxBufs) sl@0: break; sl@0: if (!(aBufferFlags & EShPoolAllocCanWait)) sl@0: { sl@0: // Give the Management DFC some time to run, then try allocating again sl@0: User::After(1000000); // 1 second sl@0: r = buf.Alloc(pool); sl@0: if (r) sl@0: { sl@0: test.Printf(_L("Alloc fail after %d of %d; Free==%u (expected %u)\n"), sl@0: bufarray.Count(), info.iMaxBufs, pool.FreeCount(), model.FreeCount()); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: model.Alloc(); sl@0: if (!(aBufferFlags & EShPoolAllocNoMap)) sl@0: { sl@0: TPtr8 ptr(buf.Ptr(), buf.Size(),buf.Size()); sl@0: ptr.Fill(bufarray.Count() % 256); sl@0: } sl@0: bufarray.Append(buf); sl@0: } sl@0: } sl@0: while (r == KErrNone); sl@0: sl@0: test_Equal(KErrNoMemory, r); sl@0: test_Equal(info.iMaxBufs, bufarray.Count()); sl@0: test_Equal(0, pool.FreeCount()); sl@0: sl@0: // Now free no more than 1/3 of these buffers... sl@0: while ((TUint) bufarray.Count() > 2 * info.iMaxBufs / 3) sl@0: { sl@0: // remove buffers from the back of the array sl@0: if (!(aBufferFlags & EShPoolAllocNoMap)) sl@0: { sl@0: TPtr8 ptr(bufarray[bufarray.Count() - 1].Ptr(), bufarray[bufarray.Count() - 1].Size(),bufarray[bufarray.Count() - 1].Size()); sl@0: ptr.Fill((bufarray.Count() + 1) % 256); sl@0: } sl@0: bufarray[bufarray.Count() - 1].Close(); sl@0: bufarray.Remove(bufarray.Count() - 1); sl@0: model.Free(); sl@0: sl@0: timeout = KTestFreeCountTimeOut / KTestWaitBeforeRetry; sl@0: while (model.FreeCount() != pool.FreeCount()) sl@0: { sl@0: User::After(KTestWaitBeforeRetry); sl@0: test_Assert(--timeout, sl@0: test.Printf(_L("Timeout: Free==%u (expected %u)\n"), pool.FreeCount(), model.FreeCount()); sl@0: model.DisplayCounters(); sl@0: ); sl@0: if ((timeout * KTestWaitBeforeRetry) % 1000000 == 0) sl@0: { sl@0: test.Printf(_L("Time out in %d seconds! (line %d)\n"), timeout * KTestWaitBeforeRetry / 1000000, __LINE__); sl@0: } sl@0: } sl@0: } sl@0: sl@0: // ... and re-allocate them sl@0: do sl@0: { sl@0: timeout = KTestFreeCountTimeOut / KTestWaitBeforeRetry; sl@0: while (model.FreeCount() != pool.FreeCount()) sl@0: { sl@0: User::After(KTestWaitBeforeRetry); sl@0: test_Assert(--timeout, sl@0: test.Printf(_L("Timeout: Free==%u (expected %u)\n"), pool.FreeCount(), model.FreeCount()); sl@0: model.DisplayCounters(); sl@0: ); sl@0: if ((timeout * KTestWaitBeforeRetry) % 1000000 == 0) sl@0: { sl@0: test.Printf(_L("Time out in %d seconds! (line %d)\n"), timeout * KTestWaitBeforeRetry / 1000000, __LINE__); sl@0: } sl@0: } sl@0: RShBuf buf; sl@0: r = buf.Alloc(pool, aBufferFlags); sl@0: if (r == KErrNoMemory) sl@0: { sl@0: // We expect to get a failure when all buffers are allocated sl@0: if ((TUint) bufarray.Count() == info.iMaxBufs) sl@0: break; sl@0: if (!(aBufferFlags & EShPoolAllocCanWait)) sl@0: { sl@0: // Give the Management DFC some time to run, then try allocating again sl@0: User::After(1000000); // 1 second sl@0: r = buf.Alloc(pool); sl@0: if (r) sl@0: { sl@0: test.Printf(_L("Alloc fail after %d of %d; Free==%u (expected %u)\n"), sl@0: bufarray.Count(), info.iMaxBufs, pool.FreeCount(), model.FreeCount()); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: model.Alloc(); sl@0: if (!(aBufferFlags & EShPoolAllocNoMap)) sl@0: { sl@0: TPtr8 ptr(buf.Ptr(), buf.Size(),buf.Size()); sl@0: ptr.Fill(bufarray.Count() % 256); sl@0: } sl@0: bufarray.Append(buf); sl@0: } sl@0: } sl@0: while (r == KErrNone); sl@0: sl@0: test_Equal(KErrNoMemory, r); sl@0: test_Equal(info.iMaxBufs, bufarray.Count()); sl@0: test_Equal(0, pool.FreeCount()); sl@0: sl@0: // Free all buffers sl@0: while (bufarray.Count()) sl@0: { sl@0: // remove buffers from the back of the array sl@0: if (!(aBufferFlags & EShPoolAllocNoMap)) sl@0: { sl@0: TPtr8 ptr(bufarray[bufarray.Count() - 1].Ptr(), bufarray[bufarray.Count() - 1].Size(),bufarray[bufarray.Count() - 1].Size()); sl@0: ptr.Fill((bufarray.Count() + 1) % 256); sl@0: } sl@0: bufarray[bufarray.Count() - 1].Close(); sl@0: bufarray.Remove(bufarray.Count() - 1); sl@0: model.Free(); sl@0: sl@0: timeout = KTestFreeCountTimeOut / KTestWaitBeforeRetry; sl@0: while (model.FreeCount() != pool.FreeCount()) sl@0: { sl@0: User::After(KTestWaitBeforeRetry); sl@0: test_Assert(--timeout, sl@0: test.Printf(_L("Timeout: Free==%u (expected %u)\n"), pool.FreeCount(), model.FreeCount()); sl@0: model.DisplayCounters(); sl@0: ); sl@0: if ((timeout * KTestWaitBeforeRetry) % 1000000 == 0) sl@0: { sl@0: test.Printf(_L("Time out in %d seconds! (line %d)\n"), timeout * KTestWaitBeforeRetry / 1000000, __LINE__); sl@0: } sl@0: } sl@0: } sl@0: sl@0: // Pool should have shrunk back to its initial size sl@0: test_Equal(info.iInitialBufs, pool.FreeCount()); sl@0: bufarray.Close(); sl@0: pool.Close(); sl@0: } sl@0: sl@0: void PoolGrowingUser() sl@0: { sl@0: test.Next(_L("Pool Growing/Shrinking (User)")); sl@0: TInt r; sl@0: TInt pagesize; sl@0: r = HAL::Get(HAL::EMemoryPageSize, pagesize); sl@0: test_KErrNone(r); sl@0: // Pool A: Non-page aligned pool (64-byte alignment) sl@0: { sl@0: TInt alignment = 6; sl@0: TInt maxbufs = KTestPoolSizeInBytes / RoundUp(*PtrBufSize, alignment); sl@0: if (maxbufs > 32000) sl@0: { sl@0: maxbufs = 32000; sl@0: } sl@0: TInt initialbufs = maxbufs / 2; sl@0: TInt growtrigger = 32; sl@0: TInt growby = 32; sl@0: TInt shrinkhys = 288; sl@0: test.Printf(_L("POOL A: BufSize=%d InitialBufs=%d MaxBufs=%d GrowTrigger=%d GrowBy=%d ShrinkHys=%d Alignment=%d\n"), sl@0: *PtrBufSize, initialbufs, maxbufs, growtrigger, growby, shrinkhys, alignment); sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, *PtrBufSize, initialbufs, alignment); sl@0: r = inf.SetSizingAttributes(maxbufs, growtrigger, growby, shrinkhys); sl@0: test_KErrNone(r); sl@0: PoolGrowingTestRoutine(inf); sl@0: } sl@0: sl@0: // Pool B: Non-page aligned pool (maximum alignment) sl@0: { sl@0: TInt alignment = Log2(pagesize); sl@0: TInt maxbufs = KTestPoolSizeInBytes / RoundUp(*PtrBufSize, alignment); sl@0: if (maxbufs > 32000) sl@0: { sl@0: maxbufs = 32000; sl@0: } sl@0: TInt initialbufs = maxbufs / 4; sl@0: TInt growtrigger = 32; sl@0: TInt growby = 32; sl@0: TInt shrinkhys = 288; sl@0: test.Printf(_L("POOL B: BufSize=%d InitialBufs=%d MaxBufs=%d GrowTrigger=%d GrowBy=%d ShrinkHys=%d Alignment=%d\n"), sl@0: *PtrBufSize, initialbufs, maxbufs, growtrigger, growby, shrinkhys, alignment); sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, *PtrBufSize, initialbufs, alignment); sl@0: r = inf.SetSizingAttributes(maxbufs, growtrigger, growby, shrinkhys); sl@0: test_KErrNone(r); sl@0: PoolGrowingTestRoutine(inf); sl@0: } sl@0: sl@0: // Pool C: Page aligned pool without guard pages sl@0: { sl@0: TInt maxbufs = KTestPoolSizeInBytes / RoundUp(*PtrBufSize, Log2(pagesize)); sl@0: if (maxbufs > 32000) sl@0: { sl@0: maxbufs = 32000; sl@0: } sl@0: TInt initialbufs = maxbufs * 3 / 8; sl@0: TInt growtrigger = 32; sl@0: TInt growby = 32; sl@0: TInt shrinkhys = 288; sl@0: test.Printf(_L("POOL C: BufSize=%d InitialBufs=%d MaxBufs=%d GrowTrigger=%d GrowBy=%d ShrinkHys=%d Page-Aligned\n"), sl@0: *PtrBufSize, initialbufs, maxbufs, growtrigger, growby, shrinkhys); sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize, initialbufs); sl@0: r = inf.SetSizingAttributes(maxbufs, growtrigger, growby, shrinkhys); sl@0: test_KErrNone(r); sl@0: PoolGrowingTestRoutine(inf); sl@0: } sl@0: sl@0: // Pool D: Page aligned pool without guard pages sl@0: { sl@0: TInt maxbufs = KTestPoolSizeInBytes / RoundUp(*PtrBufSize, Log2(pagesize)); sl@0: if (maxbufs > 32000) sl@0: { sl@0: maxbufs = 32000; sl@0: } sl@0: TInt initialbufs = maxbufs / 2; sl@0: TInt growtrigger = 32; sl@0: TInt growby = 32; sl@0: TInt shrinkhys = 288; sl@0: test.Printf(_L("POOL D: BufSize=%d InitialBufs=%d MaxBufs=%d GrowTrigger=%d GrowBy=%d ShrinkHys=%d Page-Aligned+Guard\n"), sl@0: *PtrBufSize, initialbufs, maxbufs, growtrigger, growby, shrinkhys); sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize, initialbufs); sl@0: r = inf.SetSizingAttributes(maxbufs, growtrigger, growby, shrinkhys); sl@0: test_KErrNone(r); sl@0: r = inf.SetGuardPages(); sl@0: test_KErrNone(r); sl@0: PoolGrowingTestRoutine(inf); sl@0: } sl@0: sl@0: // Pool A': Non-page aligned pool (64-byte alignment) sl@0: { sl@0: TInt alignment = 6; sl@0: TInt maxbufs = KTestPoolSizeInBytes / RoundUp(*PtrBufSize, alignment); sl@0: if (maxbufs > 32000) sl@0: { sl@0: maxbufs = 32000; sl@0: } sl@0: TInt initialbufs = 1; sl@0: TInt growtrigger = 32; sl@0: TInt growby = 256; sl@0: TInt shrinkhys = 512; sl@0: test.Printf(_L("POOL A': BufSize=%d InitialBufs=%d MaxBufs=%d GrowTrigger=%d GrowBy=%d ShrinkHys=%d Alignment=%d\n"), sl@0: *PtrBufSize, initialbufs, maxbufs, growtrigger, growby, shrinkhys, alignment); sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, *PtrBufSize, initialbufs, alignment); sl@0: r = inf.SetSizingAttributes(maxbufs, growtrigger, growby, shrinkhys); sl@0: test_KErrNone(r); sl@0: PoolGrowingTestRoutine(inf); sl@0: } sl@0: sl@0: // Pool A'': Non-page aligned pool (64-byte alignment) - AllocCanWait sl@0: { sl@0: TInt alignment = 6; sl@0: TInt maxbufs = KTestPoolSizeInBytes / RoundUp(*PtrBufSize, alignment); sl@0: if (maxbufs > 32000) sl@0: { sl@0: maxbufs = 32000; sl@0: } sl@0: TInt initialbufs = 1; sl@0: TInt growtrigger = 1; sl@0: TInt growby = 1; sl@0: TInt shrinkhys = 257; sl@0: test.Printf(_L("POOL A'': BufSize=%d InitialBufs=%d MaxBufs=%d GrowTrigger=%d GrowBy=%d ShrinkHys=%d Alignment=%d\n"), sl@0: *PtrBufSize, initialbufs, maxbufs, growtrigger, growby, shrinkhys, alignment); sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, *PtrBufSize, initialbufs, alignment); sl@0: r = inf.SetSizingAttributes(maxbufs, growtrigger, growby, shrinkhys); sl@0: test_KErrNone(r); sl@0: PoolGrowingTestRoutine(inf, EShPoolAllocCanWait); sl@0: } sl@0: sl@0: // Pool D': Page aligned pool without guard pages sl@0: { sl@0: TInt maxbufs = KTestPoolSizeInBytes / RoundUp(*PtrBufSize, Log2(pagesize)); sl@0: if (maxbufs > 32000) sl@0: { sl@0: maxbufs = 32000; sl@0: } sl@0: TInt initialbufs = 1; sl@0: TInt growtrigger = 1; sl@0: TInt growby = 1024; sl@0: TInt shrinkhys = 2048; sl@0: test.Printf(_L("POOL D': BufSize=%d InitialBufs=%d MaxBufs=%d GrowTrigger=%d GrowBy=%d ShrinkHys=%d Page-Aligned+Guard\n"), sl@0: *PtrBufSize, initialbufs, maxbufs, growtrigger, growby, shrinkhys); sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize, initialbufs); sl@0: r = inf.SetSizingAttributes(maxbufs, growtrigger, growby, shrinkhys); sl@0: test_KErrNone(r); sl@0: r = inf.SetGuardPages(); sl@0: test_KErrNone(r); sl@0: PoolGrowingTestRoutine(inf); sl@0: } sl@0: // Pool D'': Page aligned pool without guard pages - NoBufferMap sl@0: { sl@0: TInt maxbufs = KTestPoolSizeInBytes / RoundUp(*PtrBufSize, Log2(pagesize)); sl@0: if (maxbufs > 32000) sl@0: { sl@0: maxbufs = 32000; sl@0: } sl@0: TInt initialbufs = maxbufs / 2; sl@0: TInt growtrigger = 32; sl@0: TInt growby = 32; sl@0: TInt shrinkhys = 288; sl@0: test.Printf(_L("POOL D'': BufSize=%d InitialBufs=%d MaxBufs=%d GrowTrigger=%d GrowBy=%d ShrinkHys=%d Page-Aligned+Guard\n"), sl@0: *PtrBufSize, initialbufs, maxbufs, growtrigger, growby, shrinkhys); sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize, initialbufs); sl@0: r = inf.SetSizingAttributes(maxbufs, growtrigger, growby, shrinkhys); sl@0: test_KErrNone(r); sl@0: r = inf.SetGuardPages(); sl@0: test_KErrNone(r); sl@0: PoolGrowingTestRoutine(inf, EShPoolAllocNoMap); sl@0: } sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID X3 sl@0: @SYMTestCaseDesc Contiguous buffer allocation sl@0: @SYMREQ REQ11423 sl@0: @SYMTestActions sl@0: Create a pool with the Contiguous attribute and allocate buffers. sl@0: @SYMTestExpectedResults sl@0: Buffers memory is physically contiguous. sl@0: @SYMTestPriority High sl@0: */ sl@0: sl@0: void ContiguousPoolKernel() sl@0: { sl@0: test.Next(_L("Contiguous Pool (Kernel)")); sl@0: #ifdef __WINS__ sl@0: test.Printf(_L("Does not run on the emulator. Skipped\n")); sl@0: #else sl@0: TInt r; sl@0: TInt pagesize; sl@0: r = HAL::Get(HAL::EMemoryPageSize, pagesize); sl@0: test_KErrNone(r); sl@0: if (*PtrBufSize <= pagesize) sl@0: { sl@0: test.Printf(_L("Buffer size <= page size. Skipped.\n")); sl@0: return; sl@0: } sl@0: sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize, KTestPoolSizeInBufs); sl@0: // r = inf.SetSizingAttributes(KTestPoolSizeInBufs, 25, 25, 25600); sl@0: // test_KErrNone(r); sl@0: sl@0: r = Ldd.ContiguousPoolKernel(inf); sl@0: test_KErrNone(r); sl@0: sl@0: #endif // __WINS__ sl@0: } sl@0: sl@0: void ShBufPin() sl@0: { sl@0: test.Next(_L("Buffer pinning")); sl@0: #ifdef __WINS__ sl@0: test.Printf(_L("Does not run on the emulator. Skipped\n")); sl@0: #else sl@0: TInt r; sl@0: RShPool pool1; sl@0: RShBuf buf1; sl@0: TShPoolCreateInfo inf1(TShPoolCreateInfo::ENonPageAlignedBuffer, *PtrBufSize * KTestPoolSizeInBufs, 1, KTestMinimumAlignmentLog2); sl@0: r = pool1.Create(inf1, KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: r = buf1.Alloc(pool1); sl@0: test_KErrNone(r); sl@0: r = Ldd.PinBuffer(pool1.Handle(), buf1.Handle()); sl@0: test_KErrNone(r); sl@0: buf1.Close(); sl@0: pool1.Close(); sl@0: sl@0: RShPool pool2; sl@0: RShBuf buf2; sl@0: TShPoolCreateInfo inf2(TShPoolCreateInfo::ENonPageAlignedBuffer, *PtrBufSize * KTestPoolSizeInBufs, 1, KTestMinimumAlignmentLog2); sl@0: r = pool2.Create(inf2, KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: r = buf2.Alloc(pool2); sl@0: test_KErrNone(r); sl@0: r = Ldd.PinBuffer(pool2.Handle(), buf2.Handle()); sl@0: test_KErrNone(r); sl@0: buf2.Close(); sl@0: pool2.Close(); sl@0: #endif // _WINS_ sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID sl@0: @SYMTestCaseDesc sl@0: @SYMREQ sl@0: @SYMTestActions sl@0: @SYMTestExpectedResults sl@0: @SYMTestPriority sl@0: */ sl@0: sl@0: void SingleBufferPool() sl@0: { sl@0: test.Next(_L("Single Buffer Pool")); sl@0: TInt r; sl@0: sl@0: RShPool pool; sl@0: RShBuf buf; sl@0: RShBuf buf2; sl@0: sl@0: TShPoolCreateInfo infpa(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize * KTestPoolSizeInBufs, 1); sl@0: r = infpa.SetGuardPages(); sl@0: test_KErrNone(r); sl@0: r = pool.Create(infpa, KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: r = pool.SetBufferWindow(-1, ETrue); sl@0: test_KErrNone(r); sl@0: r = buf.Alloc(pool); sl@0: test_KErrNone(r); sl@0: r = buf2.Alloc(pool); sl@0: test_Equal(KErrNoMemory, r); sl@0: TPtr8(buf.Ptr(), buf.Size(), buf.Size()).Fill('!'); sl@0: buf.Close(); sl@0: pool.Close(); sl@0: sl@0: TShPoolCreateInfo infnpa(TShPoolCreateInfo::ENonPageAlignedBuffer, *PtrBufSize * KTestPoolSizeInBufs, 1, KTestMinimumAlignmentLog2); sl@0: r = pool.Create(infnpa, KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: r = buf.Alloc(pool); sl@0: test_KErrNone(r); sl@0: r = buf2.Alloc(pool); sl@0: test_Equal(KErrNoMemory, r); sl@0: TPtr8(buf.Ptr(), buf.Size(),buf.Size()).Fill('?'); sl@0: buf.Close(); sl@0: pool.Close(); sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID X4 sl@0: @SYMTestCaseDesc Negative tests (user/kernel) sl@0: @SYMREQ REQ11423 sl@0: @SYMTestActions sl@0: API calls with invalid arguments. sl@0: @SYMTestExpectedResults sl@0: Appropriate error code returned. sl@0: @SYMTestPriority High sl@0: */ sl@0: sl@0: void NegativeTestsUser() sl@0: { sl@0: test.Next(_L("Negative tests (User)")); sl@0: TInt r; sl@0: TInt pagesize; sl@0: TInt ram; sl@0: r = HAL::Get(HAL::EMemoryPageSize, pagesize); sl@0: test_KErrNone(r); sl@0: r = HAL::Get(HAL::EMemoryRAM, ram); sl@0: test_KErrNone(r); sl@0: sl@0: RShPool pool; sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 100, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 0, 100); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, KMaxTUint, 10); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 10, KMaxTUint); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, KMaxTUint, KMaxTUint); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 65537, 65536); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 10, 1 + (1 << (32 - Log2(pagesize)))); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 4096, 10); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrNone, r); pool.Close(); } sl@0: // XXX The following test will need updating in Phase 2, when exclusive access will be supported sl@0: // (page-aligned-buffer pools only) sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 4096, 10); inf.SetExclusive(); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrNotSupported, r); pool.Close(); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 4096, 10, 12); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrNone, r); pool.Close(); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 4096, 10, 12); inf.SetExclusive(); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); pool.Close(); } sl@0: #ifndef __WINS__ sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 128 * pagesize, (ram / (128 * pagesize)) + 1); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrNoMemory, r); } sl@0: #endif sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 0, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 100, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 0, 100, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, KMaxTUint, 10, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 10, KMaxTUint, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, KMaxTUint, KMaxTUint, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 65537, 65536, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 10, 10, KMaxTUint); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 10, 10, 33); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 10, 300, 24); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 10, 65537, 16); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: { TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 10, 10, Log2(pagesize) + 1); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); } sl@0: sl@0: { sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, *BufferSize, KTestPoolSizeInBufs, 0); sl@0: inf.SetGuardPages(); sl@0: r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); sl@0: r = inf.SetSizingAttributes(KTestPoolSizeInBufs - 1, 25, 25, 280); test_KErrNone(r); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); sl@0: // Either grow trigger ratio or grow by ratio == 0 => non-growable pool sl@0: // Such pools must have initial buffers == max buffers sl@0: r = inf.SetSizingAttributes(KTestPoolSizeInBufs * 2, 1, 0, 1); test_Equal(KErrArgument, r); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); sl@0: r = inf.SetSizingAttributes(KTestPoolSizeInBufs * 2, 1, 0, 0); test_Equal(KErrArgument, r); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); sl@0: // shrink hysteresis ratio must be > 256 sl@0: r = inf.SetSizingAttributes(KTestPoolSizeInBufs - 1, 25, 25, 256); test_Equal(KErrArgument, r); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); sl@0: // grow ratio must be < 256 sl@0: r = inf.SetSizingAttributes(KTestPoolSizeInBufs * 2, 256, 25, 260); test_Equal(KErrArgument, r); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); sl@0: } sl@0: sl@0: // Can't have a non-aligned, contiguous pool that grows sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 200, 10, 0); sl@0: r = inf.SetSizingAttributes(KTestPoolSizeInBufs * 2, 25, 25, 280); sl@0: test_KErrNone(r); sl@0: } sl@0: sl@0: void NegativeTestsKernel() sl@0: { sl@0: test.Next(_L("Negative tests (Kernel)")); sl@0: TInt r; sl@0: r = Ldd.NegativeTestsKernel(); sl@0: test_KErrNone(r); sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID 23 sl@0: @SYMTestCaseDesc Out of memory testing sl@0: @SYMREQ sl@0: @SYMTestActions sl@0: TBD sl@0: @SYMTestExpectedResults sl@0: @SYMTestPriority High sl@0: */ sl@0: sl@0: void OutOfMemory() sl@0: { sl@0: test.Next(_L("Out of memory")); sl@0: #ifdef _DEBUG sl@0: sl@0: sl@0: const TInt KMaxKernelAllocations = 1024; sl@0: TInt i, r; sl@0: RShPool pool; sl@0: TShPoolCreateInfo inf0(TShPoolCreateInfo::EPageAlignedBuffer, *PtrBufSize, 1); sl@0: TShPoolCreateInfo inf1(TShPoolCreateInfo::ENonPageAlignedBuffer, *PtrBufSize, 1, 0); sl@0: r = inf0.SetSizingAttributes(4, 100, 1024, 300); sl@0: test_KErrNone(r); sl@0: r = inf1.SetSizingAttributes(4, 100, 1024, 300); sl@0: test_KErrNone(r); sl@0: sl@0: for(TInt j = 0; j <= 1; j++) sl@0: { sl@0: sl@0: if(j == 0) sl@0: test.Printf(_L("OOM testing for page-aligned pool\n")); sl@0: else sl@0: test.Printf(_L("OOM testing for non-page-aligned pool\n")); sl@0: sl@0: r = KErrNoMemory; sl@0: sl@0: __KHEAP_RESET; sl@0: sl@0: //Create the pool sl@0: for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++) sl@0: { sl@0: __KHEAP_FAILNEXT(i); sl@0: if(j == 0) sl@0: r = pool.Create(inf0,KDefaultPoolHandleFlags); sl@0: else sl@0: r = pool.Create(inf1,KDefaultPoolHandleFlags); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("Create pool took %d tries\n"),i); sl@0: test_KErrNone(r); sl@0: sl@0: //Allocate buffers with automatic pool growing enabled sl@0: r = KErrNoMemory; sl@0: RShBuf buf1; sl@0: for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++) sl@0: { sl@0: __KHEAP_FAILNEXT(i); sl@0: if(j == 0) sl@0: r = buf1.Alloc(pool, EShPoolAllocNoMap); sl@0: else sl@0: r = buf1.Alloc(pool); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("Allocate shared buffer 1 took %d tries\n"),i); sl@0: test_KErrNone(r); sl@0: sl@0: // delay to allow the pool to grow sl@0: User::After(20000); sl@0: sl@0: r = KErrNoMemory; sl@0: RShBuf buf2; sl@0: for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++) sl@0: { sl@0: __KHEAP_FAILNEXT(i); sl@0: if(j == 0) sl@0: r = buf2.Alloc(pool, EShPoolAllocNoMap); sl@0: else sl@0: r = buf2.Alloc(pool); sl@0: __KHEAP_RESET; sl@0: User::After(20000); sl@0: } sl@0: test.Printf(_L("Allocate shared buffer 2 took %d tries\n"),i); sl@0: test_KErrNone(r); sl@0: sl@0: // delay to allow the pool to grow again sl@0: User::After(20000); sl@0: sl@0: r = KErrNoMemory; sl@0: RShBuf buf3; sl@0: for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++) sl@0: { sl@0: __KHEAP_FAILNEXT(i); sl@0: if(j == 0) sl@0: r = buf3.Alloc(pool, EShPoolAllocNoMap); sl@0: else sl@0: r = buf3.Alloc(pool); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("Allocate shared buffer 3 took %d tries\n"),i); sl@0: test_KErrNone(r); sl@0: sl@0: //Map a buffer in page-aligned-pool case sl@0: if(j == 0) sl@0: { sl@0: //Open a one-buffer window sl@0: r = pool.SetBufferWindow(1, ETrue); sl@0: test_KErrNone(r); sl@0: sl@0: //Map a buffer sl@0: r = KErrNoMemory; sl@0: for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++) sl@0: { sl@0: buf1.UnMap(); sl@0: __KHEAP_FAILNEXT(i); sl@0: r = buf1.Map(); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("Mapping buffer 1 took %d tries\n"),i); sl@0: test_KErrNone(r); sl@0: } sl@0: sl@0: //Setup low-space notification sl@0: TRequestStatus low; sl@0: low = KErrNoMemory; sl@0: for (i = 0; i < KMaxKernelAllocations && low != KRequestPending; i++) sl@0: { sl@0: __KHEAP_FAILNEXT(i); sl@0: pool.RequestLowSpaceNotification(1, low); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("Setting up low-space notification took %d tries\n"),i); sl@0: test_Equal(low.Int(), KRequestPending); sl@0: sl@0: //Setup free-space notification sl@0: TRequestStatus free; sl@0: free = KErrNoMemory; sl@0: for (i = 0; i < KMaxKernelAllocations && free != KRequestPending; i++) sl@0: { sl@0: __KHEAP_FAILNEXT(i); sl@0: pool.RequestFreeSpaceNotification(4, free); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("Setting up free-space notification took %d tries\n"),i); sl@0: test_Equal(free.Int(), KRequestPending); sl@0: sl@0: //No allocations should occur here sl@0: __KHEAP_FAILNEXT(1); sl@0: if(j == 0) sl@0: { sl@0: //Unmap the buffer sl@0: r = buf1.UnMap(); sl@0: } sl@0: sl@0: //Cancel the notifications sl@0: pool.CancelLowSpaceNotification(low); sl@0: pool.CancelFreeSpaceNotification(free); sl@0: sl@0: //Close the buffers and the pool sl@0: buf1.Close(); sl@0: buf2.Close(); sl@0: buf3.Close(); sl@0: pool.Close(); sl@0: __KHEAP_RESET; sl@0: sl@0: } sl@0: sl@0: // Allocate kernel-side buffer on Pool 2 sl@0: TInt handle = 0; sl@0: RShBuf kbuf; sl@0: r = KErrNoMemory; sl@0: for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++) sl@0: { sl@0: __KHEAP_FAILNEXT(i); sl@0: r = Ldd.AllocateKernelBuffer(1, handle); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("Allocate kernel buffer took %d tries\n"),i); sl@0: test_KErrNone(r); sl@0: sl@0: __KHEAP_FAILNEXT(1); sl@0: kbuf.SetHandle(handle); sl@0: __KHEAP_RESET; sl@0: sl@0: r = KErrNoMemory; sl@0: for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++) sl@0: { sl@0: r = kbuf.UnMap(); sl@0: __KHEAP_FAILNEXT(i); sl@0: r = kbuf.Map(); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("Mapping kernel buffer took %d tries\n"),i); sl@0: test_KErrNone(r); sl@0: sl@0: __KHEAP_FAILNEXT(1); sl@0: r = kbuf.UnMap(); sl@0: kbuf.Close(); sl@0: __KHEAP_RESET; sl@0: sl@0: sl@0: #else // _DEBUG sl@0: test.Printf(_L("Debug builds only. Test skipped.")); sl@0: #endif // _DEBUG sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID 22 sl@0: @SYMTestCaseDesc Stress testing sl@0: @SYMREQ sl@0: @SYMTestActions sl@0: TBD sl@0: @SYMTestExpectedResults sl@0: @SYMTestPriority Medium sl@0: */ sl@0: sl@0: TInt StressThread1(TAny*) sl@0: { sl@0: TInt r; sl@0: TInt pagesize; sl@0: r = HAL::Get(HAL::EMemoryPageSize, pagesize); sl@0: test_KErrNone(r); sl@0: sl@0: TInt i = 0; sl@0: FOREVER sl@0: { sl@0: RShPool pool; sl@0: if (i % 2) sl@0: { sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 1000, 512); sl@0: r = pool.Create(inf,KDefaultPoolHandleFlags); sl@0: if (r) sl@0: { sl@0: RDebug::Printf("Error %d line %d", r, __LINE__); sl@0: break; sl@0: } sl@0: sl@0: r = pool.SetBufferWindow(-1, ETrue); sl@0: test_KErrNone(r); sl@0: sl@0: } sl@0: else sl@0: { sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 10000, 200, 0); sl@0: r = pool.Create(inf,KDefaultPoolHandleFlags); sl@0: if (r) sl@0: { sl@0: RDebug::Printf("Error %d line %d", r, __LINE__); sl@0: break; sl@0: } sl@0: } sl@0: pool.Close(); sl@0: i++; sl@0: if (i % 100 == 0) sl@0: { sl@0: RDebug::Printf("ST1 %d iterations", i); sl@0: } sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt StressThread2(TAny*) sl@0: { sl@0: TInt r = KErrUnknown; sl@0: TShPoolInfo inf1; sl@0: TShPoolInfo inf2; sl@0: P1.GetInfo(inf1); sl@0: P2.GetInfo(inf2); sl@0: TInt j = 0; sl@0: FOREVER sl@0: { sl@0: TUint i; sl@0: RArray bufarray1; sl@0: RArray bufarray2; sl@0: for (i = 0; i < inf1.iMaxBufs; i++) sl@0: { sl@0: RShBuf buf; sl@0: r = buf.Alloc(P1); sl@0: if (r) sl@0: { sl@0: RDebug::Printf("Error %d line %d i=%d", r, __LINE__, i); sl@0: break; sl@0: } sl@0: TPtr8(buf.Ptr(), buf.Size(),buf.Size()).Fill('1'); sl@0: r = bufarray1.Append(buf); sl@0: if (r) sl@0: { sl@0: buf.Close(); sl@0: RDebug::Printf("Error %d line %d i=%d", r, __LINE__, i); sl@0: break; sl@0: } sl@0: } sl@0: for (i = 0; i < inf2.iMaxBufs; i++) sl@0: { sl@0: RShBuf buf; sl@0: r = buf.Alloc(P2); sl@0: if (r) sl@0: { sl@0: RDebug::Printf("Error %d line %d i=%d", r, __LINE__, i); sl@0: break; sl@0: } sl@0: TPtr8(buf.Ptr(), buf.Size(),buf.Size()).Fill('2'); sl@0: bufarray2.Append(buf); sl@0: } sl@0: i = 0; sl@0: while (bufarray1.Count()) sl@0: { sl@0: bufarray1[0].Close(); sl@0: bufarray1.Remove(0); sl@0: i++; sl@0: } sl@0: sl@0: while (bufarray2.Count()) sl@0: { sl@0: bufarray2[0].Close(); sl@0: bufarray2.Remove(0); sl@0: } sl@0: bufarray1.Close(); sl@0: bufarray2.Close(); sl@0: if (r) sl@0: { sl@0: break; sl@0: } sl@0: j++; sl@0: if (j % 10 == 0) sl@0: { sl@0: RDebug::Printf("ST2 %d iterations", j); sl@0: } sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: void StressTesting(TInt aSecs) sl@0: { sl@0: test.Next(_L("Stress testing")); sl@0: TInt r; sl@0: sl@0: test.Start(_L("Create pools")); sl@0: TShPoolCreateInfo inf1(TShPoolCreateInfo::ENonPageAlignedBuffer, 2000, 500, 11); sl@0: r = P1.Create(inf1,KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: TInt handle; sl@0: TShPoolCreateInfo inf2(TShPoolCreateInfo::EPageAlignedBuffer, 5000, 150); sl@0: r = Ldd.OpenKernelPool(inf2, handle); sl@0: test_KErrNone(r); sl@0: P2.SetHandle(handle); sl@0: sl@0: r = P2.SetBufferWindow(-1, ETrue); sl@0: test_KErrNone(r); sl@0: sl@0: test.Next(_L("Create threads")); sl@0: RThread t1; sl@0: r = t1.Create(_L("THREAD1"), StressThread1, KDefaultStackSize, KMinHeapSize, KMinHeapSize, NULL); sl@0: test_KErrNone(r); sl@0: RThread t2; sl@0: r = t2.Create(_L("THREAD2"), StressThread2, KDefaultStackSize*2, KMinHeapSize, 1 << 20, NULL); sl@0: test_KErrNone(r); sl@0: test.Next(_L("Start threads")); sl@0: test.Printf(_L("Wait for %d seconds\n"), aSecs); sl@0: RThread().SetPriority(EPriorityMore); sl@0: TRequestStatus t1rs; sl@0: TRequestStatus t2rs; sl@0: t1.Logon(t1rs); sl@0: t2.Logon(t2rs); sl@0: t1.Resume(); sl@0: t2.Resume(); sl@0: User::After(aSecs * 1000000); sl@0: sl@0: test.Next(_L("Kill threads")); sl@0: t1.Kill(KErrNone); sl@0: t2.Kill(KErrNone); sl@0: sl@0: // wait for threads to actually die sl@0: User::WaitForRequest(t1rs); sl@0: User::WaitForRequest(t2rs); sl@0: sl@0: t1.Close(); sl@0: t2.Close(); sl@0: RThread().SetPriority(EPriorityNormal); sl@0: sl@0: test.Next(_L("Close pools")); sl@0: P1.Close(); sl@0: r = Ldd.CloseKernelPool(); sl@0: test_KErrNone(r); sl@0: P2.Close(); sl@0: test.End(); sl@0: } sl@0: sl@0: /* sl@0: @SYMTestCaseID sl@0: @SYMTestCaseDesc sl@0: @SYMREQ sl@0: @SYMTestActions sl@0: @SYMTestExpectedResults sl@0: @SYMTestPriority sl@0: */ sl@0: sl@0: void NoDeallocation() sl@0: { sl@0: test.Next(_L("No deallocation")); sl@0: TInt r; sl@0: TBuf<10> command; sl@0: command.Format(_L("%S %d"), &KTestSlave, ETestSlaveNoDeallocation); sl@0: RProcess p; sl@0: r = p.Create(RProcess().FileName(), command); sl@0: test_KErrNone(r); sl@0: TRequestStatus rs; sl@0: p.Logon(rs); sl@0: p.Resume(); sl@0: User::WaitForRequest(rs); sl@0: sl@0: // wait for memory to be freed sl@0: r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, (TAny*)5000, 0); sl@0: test_KErrNone(r); sl@0: sl@0: __KHEAP_MARKEND; sl@0: test_KErrNone(rs.Int()); sl@0: test_Equal(EExitKill, p.ExitType()); sl@0: test_KErrNone(p.ExitReason()); sl@0: p.Close(); sl@0: } sl@0: sl@0: TInt SlaveNoDeallocation() sl@0: { sl@0: __KHEAP_MARK; sl@0: TInt r; sl@0: RShPool pool; sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *BufferSize, KTestPoolSizeInBufs); sl@0: r = pool.Create(inf,KDefaultPoolHandleFlags); sl@0: test_KErrNone(r); sl@0: sl@0: pool.SetBufferWindow(-1, ETrue); sl@0: test_KErrNone(r); sl@0: sl@0: if (!r) sl@0: { sl@0: RShBuf buf; sl@0: r = buf.Alloc(pool); sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt E32Main() sl@0: { sl@0: __UHEAP_MARK; sl@0: sl@0: // Parse command line for slave processes sl@0: TInt r = KErrArgument; sl@0: TBuf cmd; sl@0: User::CommandLine(cmd); sl@0: TLex lex(cmd); sl@0: if (lex.NextToken() == KTestSlave) sl@0: { sl@0: TInt function; sl@0: TLex functionlex(lex.NextToken()); sl@0: functionlex.Val(function); sl@0: switch (function) sl@0: { sl@0: case ETestSlaveNoDeallocation: sl@0: r = SlaveNoDeallocation(); sl@0: break; sl@0: } sl@0: __UHEAP_MARKEND; sl@0: return r; sl@0: } sl@0: // Test starts here sl@0: test.Title(); sl@0: sl@0: test.Start(_L("Check for Shared Buffers availability")); sl@0: RShPool pool; sl@0: TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, *BufferSize, KTestPoolSizeInBufs); sl@0: r = pool.Create(inf,KDefaultPoolHandleFlags); sl@0: if (r == KErrNotSupported) sl@0: { sl@0: test.Printf(_L("Not supported by this memory model.\n")); sl@0: } sl@0: else sl@0: { sl@0: test_KErrNone(r); sl@0: pool.Close(); sl@0: sl@0: test.Next(_L("No device driver")); sl@0: test.Start(_L("Start test loop")); sl@0: for (PtrBufSize = BufferSize; *PtrBufSize != 0; PtrBufSize++) sl@0: { sl@0: TBuf<30> title; sl@0: title.Format(_L("Buffer size = %d bytes"), *PtrBufSize); sl@0: test.Next(title); sl@0: test.Start(_L("New test iteration")); sl@0: BufferAlignmentUser(); sl@0: BufferMapping(); sl@0: BufferWindow(); sl@0: GuardPages(); sl@0: PoolGrowingUser(); sl@0: SingleBufferPool(); sl@0: test.End(); sl@0: } sl@0: test.End(); sl@0: test.Next(_L("Load Device Driver")); sl@0: LoadDeviceDrivers(); sl@0: sl@0: #ifdef TEST_CLIENT_THREAD sl@0: test.Next(_L("Device driver in client thread")); sl@0: r = Ldd.Open(0); sl@0: #else sl@0: test.Next(_L("Device driver in own thread")); sl@0: r = Ldd.Open(1); sl@0: #endif sl@0: sl@0: test_KErrNone(r); sl@0: sl@0: test.Start(_L("Start test loop")); sl@0: for (PtrBufSize = BufferSize; *PtrBufSize != 0; PtrBufSize++) sl@0: { sl@0: TBuf<30> title; sl@0: title.Format(_L("Buffer size = %d bytes"), *PtrBufSize); sl@0: test.Next(title); sl@0: test.Start(_L("New test iteration")); sl@0: CreateUserPool(ETestNonPageAligned); sl@0: CreateKernelPool(ETestNonPageAligned); sl@0: AllocateUserBuffer(); sl@0: AllocateKernelBuffer(); sl@0: AllocateUserMax(P1); sl@0: AllocateUserMax(P2); sl@0: AllocateKernelMax(); sl@0: BufferAlignmentKernel(); sl@0: CreateKernelPoolPhysAddr(); sl@0: NotificationRequests(P1); sl@0: NotificationRequests(P2); sl@0: CancelNotificationRequests(P1); sl@0: CancelNotificationRequests(P2); sl@0: ShBufPin(); sl@0: CloseKernelPool(); sl@0: CloseUserPool(); sl@0: ContiguousPoolKernel(); sl@0: CreateUserPool(ETestPageAligned); sl@0: CreateKernelPool(ETestPageAligned); sl@0: OutOfMemory(); sl@0: AllocateUserBuffer(); sl@0: AllocateKernelBuffer(); sl@0: AllocateUserMax(P1); sl@0: AllocateUserMax(P2); sl@0: AllocateKernelMax(); sl@0: NotificationRequests(P1); sl@0: NotificationRequests(P2); sl@0: CloseUserPool(); sl@0: CloseKernelPool(); sl@0: CreateUserPool(ETestPageAlignedGrowing); sl@0: CreateKernelPool(ETestPageAlignedGrowing); sl@0: OutOfMemory(); sl@0: AllocateKernelMax(); sl@0: AllocateUserMax(P1); sl@0: AllocateUserMax(P2); sl@0: CloseUserPool(); sl@0: CloseKernelPool(); sl@0: test.End(); sl@0: } sl@0: NegativeTestsKernel(); sl@0: StressTesting(5); sl@0: test.End(); sl@0: Ldd.Close(); sl@0: sl@0: NegativeTestsUser(); sl@0: NoDeallocation(); sl@0: sl@0: test.Next(_L("Unload Device Drivers")); sl@0: FreeDeviceDrivers(); sl@0: } sl@0: test.End(); sl@0: test.Close(); sl@0: sl@0: __UHEAP_MARKEND; sl@0: return KErrNone; sl@0: }