diff -r 000000000000 -r a41df078684a kerneltest/e32test/mmu/t_kblockmap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mmu/t_kblockmap.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,586 @@ +// Copyright (c) 2006-2009 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" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\mmu\t_kblockmap.cpp +// Unit tests for TKernBlockMap +// 002 Test Initialise error checking +// 003 Test processing of user-side block map into extent list +// 004 Test processing of user-side block map into extent list, block size > read unit size +// 005 Test Read error checking +// 006 Test Read +// +// + +//! @SYMTestCaseID KBASE-T_KBLOCKMAP-0338 +//! @SYMTestType UT +//! @SYMPREQ PREQ1110 +//! @SYMTestCaseDesc Demand Paging Kernel Blockmap tests +//! @SYMTestActions 001 Unit tests the TKernBlockMap class +//! @SYMTestExpectedResults All tests should pass. +//! @SYMTestPriority High +//! @SYMTestStatus Implemented + +#include +#include +#include + +RTest test(_L("T_KBLOCKMAP")); + +#define test_noError(x) { TInt _r = (x); if (_r < 0) HandleError(_r, __LINE__); } +#define test_notNull(x) { TAny* _a = (TAny*)(x); if (_a == NULL) HandleNull(__LINE__); } +#define test_equal(e, a) { TInt _e = (e); TInt _a = (a); if (_e != _a) HandleNotEqual(_e, _a, __LINE__); } + +void HandleError(TInt aError, TInt aLine) + { + test.Printf(_L("Error %d\n"), aError); + test.operator()(EFalse, aLine); + } + +void HandleNull(TInt aLine) + { + test.Printf(_L("Null value\n")); + test.operator()(EFalse, aLine); + } + +void HandleNotEqual(TInt aExpected, TInt aActual, TInt aLine) + { + test.Printf(_L("Expected 0x%x but got 0x%x\n"), aExpected, aActual); + test.operator()(EFalse, aLine); + } + +/// An list of "pod" objects which can be initialised by passing a variable number of TUints to its +/// constructor +template +class CList + { +public: + CList(); + CList(TInt aCount, ...); + virtual ~CList(); + inline TInt Count() const { return iCount; } + const T* Entries() const { return iEntries; } + const T& operator[](TInt aIndex) const; +protected: + void Set(TInt aCount, VA_LIST aList); +private: + const CList& operator=(const CList&); + TInt iCount; + T* iEntries; + }; + +template +CList::CList() + : iCount(0), iEntries(NULL) + { + __ASSERT_COMPILE(sizeof(T) % sizeof(TUint32) == 0); + } + +template +CList::CList(TInt aCount, ...) + : iCount(aCount) + { + VA_LIST list; + VA_START(list, aCount); + Set(aCount, list); + } + +template +CList::~CList() + { + User::Free(iEntries); + iEntries = NULL; + } + +template +void CList::Set(TInt aCount, VA_LIST aList) + { + iCount = aCount; + test(iEntries == NULL); + iEntries = (T*)User::Alloc(sizeof(T) * iCount); + test_notNull(iEntries); + TInt argCount = iCount * (sizeof(T) / sizeof(TUint32)); + for (TInt i = 0 ; i < argCount ; ++i) + ((TUint32*)iEntries)[i] = VA_ARG(aList, TUint32); + } + +template +const T& CList::operator[](TInt aIndex) const + { + test(aIndex < iCount); + return iEntries[aIndex]; + } + +/// Holds all the data associated with the user-side representation of a block map +class CBlockMap : public CList + { +public: + CBlockMap(TUint aBlockGranularity, + TUint aBlockStartOffset, + TInt64 aStartBlockAddress, + TUint aReadUnitShift, + TUint aCodeLengthInFile, + TUint aEntriesSize, + ...); + inline const SBlockMapInfoBase& Info() const { return iInfo; } + inline TInt ReadUnitShift() const { return iReadUnitShift; } + inline TInt CodeLengthInFile() const { return iCodeLengthInFile; } + inline TInt EntriesSize() const { return iEntriesSize; } +private: + SBlockMapInfoBase iInfo; + TBlockMapEntryBase* iEntries; + TUint iReadUnitShift; + TUint iCodeLengthInFile; + TUint iEntriesSize; + }; + +CBlockMap::CBlockMap(TUint aBlockGranularity, + TUint aBlockStartOffset, + TInt64 aStartBlockAddress, + TUint aReadUnitShift, + TUint aCodeLengthInFile, + TUint aEntriesSize, + ...) + { + iInfo.iBlockGranularity = aBlockGranularity; + iInfo.iBlockStartOffset = aBlockStartOffset; + iInfo.iStartBlockAddress = aStartBlockAddress; + // don't care about iInfo.iLocalDriveNumber for test purposes + iReadUnitShift = aReadUnitShift; + iCodeLengthInFile = aCodeLengthInFile; + iEntriesSize = aEntriesSize; + iEntries = (TBlockMapEntryBase*)User::Alloc(iEntriesSize); + + VA_LIST list; + VA_START(list, aEntriesSize); + Set(iEntriesSize / sizeof(TBlockMapEntryBase), list); + } + +/// A list of extents, for comparison with those generated by the kernel block map processing code +class CExtentList : public CList + { +public: + typedef TBlockMap::SExtent SExtent; + CExtentList(TInt aCount, ...); + void Dump() const; + }; + +CExtentList::CExtentList(TInt aCount, ...) + { + VA_LIST list; + VA_START(list, aCount); + Set(aCount, list); + } + +void CExtentList::Dump() const + { + RDebug::Printf("CExtentList:\n"); + const CExtentList& self = *this; + for (TInt i = 0 ; i < Count() ; ++i) + RDebug::Printf(" %d: %08x -> %08x: %08x\n", i, self[i].iDataOffset, self[i+1].iDataOffset, self[i].iBlockNumber); + } + +TBool operator==(const TBlockMap::SExtent& a, const TBlockMap::SExtent& b) + { + return a.iDataOffset == b.iDataOffset && a.iBlockNumber == b.iBlockNumber; + } + +TBool operator!=(const TBlockMap::SExtent& a, const TBlockMap::SExtent& b) + { + return !(a == b); + } + +TBool CompareExtentsEqual(const TBlockMap& aBlockMap, const CExtentList& aExtentList) + { + if (aBlockMap.Count() != aExtentList.Count()) + return EFalse; + for (TInt i = 0 ; i < aBlockMap.Count() ; ++i) + { + if (aBlockMap.Extent(i) != aExtentList[i]) + return EFalse; + } + return ETrue; + } + +TInt MakeKernBlockMap(TBlockMap& aKbm, const CBlockMap& aUbm) + { + TBlockMapEntryBase* buffer = (TBlockMapEntryBase*)User::Alloc(aUbm.EntriesSize()); + test_notNull(buffer); + Mem::Copy(buffer, aUbm.Entries(), aUbm.EntriesSize()); + return aKbm.Initialise(aUbm.Info(), + buffer, + aUbm.EntriesSize(), + aUbm.ReadUnitShift(), + aUbm.CodeLengthInFile()); +} + +void MakeKernBlockMapAndTestExtents(const CBlockMap& aUbm, const CExtentList& aExpectedExtentList) + { + TBlockMap kbm; + test_noError(MakeKernBlockMap(kbm, aUbm)); + TBool equal = CompareExtentsEqual(kbm, aExpectedExtentList); + if (!equal) + { + aExpectedExtentList.Dump(); +#ifdef _DEBUG + kbm.Dump(); +#endif + } + test(equal); + } + +// Tests + +void TestInitialiseErrors() + { + test.Next(_L("Test Initialise error checking")); + TBlockMap kbm; + + // Block size must be a power of two + test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(513, 0, 0, 9, 1, 8, 1, 0))); + + // Block size must be greater than or equal to the read unit size + test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 10, 1, 8, 1, 0))); + + // Block start offset must be less than or equal to block size + test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 513, 0, 9, 1, 8, 1, 0))); + + // Block zero address must be a multiple of the block size + test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 1, 9, 1, 8, 1, 0))); + + // Code length in file must be greater than zero + test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 0, 8, 1, 0))); + + // Size of entries array must be multiple of the size of one entry + test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 1, 9, 1, 0))); + + // Size of entries must be non-zero + test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 1, 0))); + + // Size of block map must be greater or equal to size of data in file + test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 513, 8, 1, 0))); + } + + // blockGranularity, startOffset, blockZeroAddress, readUnitShift, codeLengthInFile, entriesSize, (numberOfBlocks, startBlock)+ + +void TestExtentList() + { + test.Next(_L("Test processing of user-side block map into extent list")); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // |= | | | | | | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 0, 0, 9, 1, 8, 1, 0), + CExtentList(1, 0, 0)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | |= | | | | | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 0, 512, 9, 1, 8, 1, 0), + CExtentList(1, 0, 1)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | | = | | | | | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1, 8, 1, 0), + CExtentList(1, -23, 1)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | | | | = | | | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1, 8, 1, 2), + CExtentList(1, -23, 3)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | | | | ======| | | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 489, 8, 1, 2), + CExtentList(1, -23, 3)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | | | | ======== | | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 600, 8, 2, 2), + CExtentList(1, -23, 3)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | | | | ==============| |== | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1100, 16, 2, 2, 1, 5), + CExtentList(2, -23, 3, 1001, 6)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | | | | ==============| |=======| | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1513, 16, 2, 2, 1, 5), + CExtentList(2, -23, 3, 1001, 6)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | | | | ==============| |=======|= | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1540, 16, 2, 2, 2, 5), + CExtentList(2, -23, 3, 1001, 6)); + } + +void TestExtentListScaled() + { + test.Next(_L("Test processing of user-side block map into extent list, block size > read unit size")); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // |= : | : | : | : | : | : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 0, 0, 8, 1, 8, 1, 0), + CExtentList(1, 0, 0)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : |= : | : | : | : | : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 0, 512, 8, 1, 8, 1, 0), + CExtentList(1, 0, 2)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | = : | : | : | : | : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 8, 1, 8, 1, 0), + CExtentList(1, -23, 2)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : = | : | : | : | : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 1, 8, 1, 0), + CExtentList(1, -24, 3)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : = | : | : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 1, 8, 1, 2), + CExtentList(1, -24, 7)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : ==| : | : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 232, 8, 1, 2), + CExtentList(1, -24, 7)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : ==== : | : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 333, 8, 2, 2), + CExtentList(1, -24, 7)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : ======== | : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 666, 8, 2, 2), + CExtentList(1, -24, 7)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : ==========| : | : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 744, 8, 2, 2), + CExtentList(1, -24, 7)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : ==========| : |== : | : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 888, 16, 2, 2, 1, 5), + CExtentList(2, -24, 7, 744, 12)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : ==========| : |=======| : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 1256, 16, 2, 2, 1, 5), + CExtentList(2, -24, 7, 744, 12)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : ==========| : |========= : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 1350, 16, 2, 2, 2, 5), + CExtentList(2, -24, 7, 744, 12)); + } + +/// Holds the expected arguments for one call to the read function +struct SReadEntry + { + TLinAddr iBuffer; + TInt iBlockNumber; + TInt iBlockCount; + }; + +/// Holds a list of expected arguments for all calls to the read function +class CReadInfo : public CList + { +public: + CReadInfo(TInt aReturnVal, TInt aCount, ...); + const SReadEntry& Next(); + void Done() const; + TInt ReturnVal() const { return iReturnVal; } +private: + TInt iPos; + TInt iReturnVal; + }; + +CReadInfo::CReadInfo(TInt aReturnVal, TInt aCount, ...) + : iPos(0), iReturnVal(aReturnVal) + { + VA_LIST list; + VA_START(list, aCount); + Set(aCount, list); + } + +const SReadEntry& CReadInfo::Next() + { + const CList& self = *this; + return self[iPos++]; + } + +void CReadInfo::Done() const + { + test_equal(Count(), iPos); + } + +TInt ReadFunc(TAny* aArg, TAny*, TLinAddr aBuffer, TInt aBlockNumber, TInt aBlockCount) + { + CReadInfo& info = *(CReadInfo*)aArg; + const SReadEntry& expected = info.Next(); + test_equal(expected.iBuffer, aBuffer); + test_equal(expected.iBlockNumber, aBlockNumber); + test_equal(expected.iBlockCount, aBlockCount); + return KErrNone; + } + +void TestRead(const TBlockMap& aBlockMap, + TLinAddr aBuffer, + TInt aPos, + TInt aLength, + TInt aReadUnitShift, + const CReadInfo& aExpected) + { + test_equal(aExpected.ReturnVal(), + aBlockMap.Read(aBuffer, aPos, aLength, aReadUnitShift, ReadFunc, (TAny*)&aExpected, (TAny*)NULL)); + aExpected.Done(); + } + +void TestReadErrors() + { + test.Next(_L("Test Read error checking")); + + TBlockMap kbm, kbm2; + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // |= | | | | | | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + test_noError(MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 1, 8, 1, 0))); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | : | : | : | : ==========| : |========= : | : | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + test_noError(MakeKernBlockMap(kbm2, CBlockMap(512, 280, 512, 8, 1350, 16, 2, 2, 2, 5))); + + // Test read start position is outside block map + TestRead(kbm, 0, 1, 1, 9, CReadInfo(KErrArgument, 0)); + TestRead(kbm2, 0, 1350, 1, 8, CReadInfo(KErrArgument, 0)); + + // Test read start position is negative + TestRead(kbm, 0, -1, 1, 9, CReadInfo(KErrArgument, 0)); + TestRead(kbm2, 0, -1, 1, 8, CReadInfo(KErrArgument, 0)); + + // Test read length exceeds block map length + TestRead(kbm, 0, 0, 2, 9, CReadInfo(KErrArgument, 1, 0, 0, 1)); + TestRead(kbm2, 0, 1349, 2, 8, CReadInfo(KErrArgument, 1, 0, 14, 1)); + } + +void TestReads() + { + test.Next(_L("Test Read")); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // |=======================| | | | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + + TBlockMap kbm2; + test_noError(MakeKernBlockMap(kbm2, CBlockMap(512, 0, 0, 9, 1536, 8, 3, 0))); + + // Test correct number of blocks read + TestRead(kbm2, 0, 0, 512, 9, CReadInfo(0, 1, 0, 0, 1)); + TestRead(kbm2, 0, 0, 513, 9, CReadInfo(0, 1, 0, 0, 2)); + TestRead(kbm2, 0, 0, 1024, 9, CReadInfo(0, 1, 0, 0, 2)); + TestRead(kbm2, 0, 0, 1025, 9, CReadInfo(0, 1, 0, 0, 3)); + TestRead(kbm2, 0, 0, 1536, 9, CReadInfo(0, 1, 0, 0, 3)); + + // Test start offset not aligned to read unit + TestRead(kbm2, 0, 1, 511, 9, CReadInfo(1, 1, 0, 0, 1)); + TestRead(kbm2, 0, 256, 256, 9, CReadInfo(256, 1, 0, 0, 1)); + TestRead(kbm2, 0, 511, 1, 9, CReadInfo(511, 1, 0, 0, 1)); + TestRead(kbm2, 0, 513, 511, 9, CReadInfo(1, 1, 0, 1, 1)); + TestRead(kbm2, 0, 1023, 1, 9, CReadInfo(511, 1, 0, 1, 1)); + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // |=======| |=======| |=======| | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + + TBlockMap kbm; + test_noError(MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 1536, 24, 1, 0, 1, 3, 1, 5))); + + // Test correct block selected for read + TestRead(kbm, 0, 0, 1, 9, CReadInfo(0, 1, 0, 0, 1)); + TestRead(kbm, 0, 256, 1, 9, CReadInfo(256, 1, 0, 0, 1)); + TestRead(kbm, 0, 511, 1, 9, CReadInfo(511, 1, 0, 0, 1)); + TestRead(kbm, 0, 512, 1, 9, CReadInfo(0, 1, 0, 3, 1)); + TestRead(kbm, 0, 768, 1, 9, CReadInfo(256, 1, 0, 3, 1)); + TestRead(kbm, 0, 1023, 1, 9, CReadInfo(511, 1, 0, 3, 1)); + TestRead(kbm, 0, 1535, 1, 9, CReadInfo(511, 1, 0, 5, 1)); + + // Test reading multiple blocks + TestRead(kbm, 0, 0, 513, 9, CReadInfo(0, 2, 0, 0, 1, 512, 3, 1)); + TestRead(kbm, 0, 0, 1024, 9, CReadInfo(0, 2, 0, 0, 1, 512, 3, 1)); + TestRead(kbm, 0, 0, 1025, 9, CReadInfo(0, 3, 0, 0, 1, 512, 3, 1, 1024, 5, 1)); + TestRead(kbm, 0, 0, 1536, 9, CReadInfo(0, 3, 0, 0, 1, 512, 3, 1, 1024, 5, 1)); + + + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + // | ====| |=======| |=======| | | | | + // +-------+-------+-------+-------+-------+-------+-------+-------+-------+------- + + TBlockMap kbm3; + test_noError(MakeKernBlockMap(kbm3, CBlockMap(512, 256, 0, 9, 1280, 24, 1, 0, 1, 3, 1, 5))); + + // Test correct block selected for read + TestRead(kbm3, 0, 0, 1, 9, CReadInfo(256, 1, 0, 0, 1)); + TestRead(kbm3, 0, 255, 1, 9, CReadInfo(511, 1, 0, 0, 1)); + TestRead(kbm3, 0, 256, 1, 9, CReadInfo(0, 1, 0, 3, 1)); + TestRead(kbm3, 0, 767, 1, 9, CReadInfo(511, 1, 0, 3, 1)); + TestRead(kbm3, 0, 768, 1, 9, CReadInfo(0, 1, 0, 5, 1)); + + // Test reading multiple blocks + TestRead(kbm3, 0, 0, 256, 9, CReadInfo(256, 1, 0, 0, 1)); + TestRead(kbm3, 0, 0, 257, 9, CReadInfo(256, 2, 0, 0, 1, 512, 3, 1)); + TestRead(kbm3, 0, 0, 768, 9, CReadInfo(256, 2, 0, 0, 1, 512, 3, 1)); + TestRead(kbm3, 0, 0, 769, 9, CReadInfo(256, 3, 0, 0, 1, 512, 3, 1, 1024, 5, 1)); + TestRead(kbm3, 0, 0, 1280, 9, CReadInfo(256, 3, 0, 0, 1, 512, 3, 1, 1024, 5, 1)); + } + +TInt E32Main() + { + test.Title(); + test.Start(_L("Unit tests the TKernBlockMap class")); + + TestInitialiseErrors(); + TestExtentList(); + TestExtentListScaled(); + TestReadErrors(); + TestReads(); + + test.End(); + + return KErrNone; + }