kerneltest/e32test/mmu/t_kblockmap.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:26:05 +0100
branchRCL_3
changeset 29 743008598095
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// 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 <e32test.h>
#include <e32debug.h>
#include <memmodel/epoc/mmubase/kblockmap.h>

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 T>
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<T>& operator=(const CList<T>&);
	TInt iCount;
	T* iEntries;
	};

template <class T>
CList<T>::CList()
	: iCount(0), iEntries(NULL)
	{
	__ASSERT_COMPILE(sizeof(T) % sizeof(TUint32) == 0);
	}

template <class T>
CList<T>::CList(TInt aCount, ...)
	: iCount(aCount)
	{
	VA_LIST list;
	VA_START(list, aCount);
	Set(aCount, list);
	}

template <class T>
CList<T>::~CList()
	{
	User::Free(iEntries);
	iEntries = NULL;
	}

template <class T>
void CList<T>::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 <class T>
const T& CList<T>::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<TBlockMapEntryBase>
	{
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<TBlockMap::SExtent>
	{
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<SReadEntry>
	{
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<SReadEntry>& 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;
	}