kerneltest/e32test/mmu/t_kblockmap.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\mmu\t_kblockmap.cpp
       
    15 // Unit tests for TKernBlockMap
       
    16 // 002 Test Initialise error checking
       
    17 // 003 Test processing of user-side block map into extent list
       
    18 // 004 Test processing of user-side block map into extent list, block size > read unit size
       
    19 // 005 Test Read error checking
       
    20 // 006 Test Read
       
    21 // 
       
    22 //
       
    23 
       
    24 //! @SYMTestCaseID			KBASE-T_KBLOCKMAP-0338
       
    25 //! @SYMTestType			UT
       
    26 //! @SYMPREQ				PREQ1110
       
    27 //! @SYMTestCaseDesc		Demand Paging Kernel Blockmap tests
       
    28 //! @SYMTestActions			001 Unit tests the TKernBlockMap class
       
    29 //! @SYMTestExpectedResults All tests should pass.
       
    30 //! @SYMTestPriority        High
       
    31 //! @SYMTestStatus          Implemented
       
    32 
       
    33 #include <e32test.h>
       
    34 #include <e32debug.h>
       
    35 #include <memmodel/epoc/mmubase/kblockmap.h>
       
    36 
       
    37 RTest test(_L("T_KBLOCKMAP"));
       
    38 
       
    39 #define test_noError(x) { TInt _r = (x); if (_r < 0) HandleError(_r, __LINE__); }
       
    40 #define test_notNull(x) { TAny* _a = (TAny*)(x); if (_a == NULL) HandleNull(__LINE__); }
       
    41 #define test_equal(e, a) { TInt _e = (e); TInt _a = (a); if (_e != _a) HandleNotEqual(_e, _a, __LINE__); }
       
    42 
       
    43 void HandleError(TInt aError, TInt aLine)
       
    44 	{
       
    45 	test.Printf(_L("Error %d\n"), aError);
       
    46 	test.operator()(EFalse, aLine);
       
    47 	}
       
    48 
       
    49 void HandleNull(TInt aLine)
       
    50 	{
       
    51 	test.Printf(_L("Null value\n"));
       
    52 	test.operator()(EFalse, aLine);
       
    53 	}
       
    54 
       
    55 void HandleNotEqual(TInt aExpected, TInt aActual, TInt aLine)
       
    56 	{
       
    57 	test.Printf(_L("Expected 0x%x but got 0x%x\n"), aExpected, aActual);
       
    58 	test.operator()(EFalse, aLine);
       
    59 	}
       
    60 
       
    61 /// An list of "pod" objects which can be initialised by passing a variable number of TUints to its
       
    62 /// constructor
       
    63 template <class T>
       
    64 class CList
       
    65 	{
       
    66 public:
       
    67 	CList();
       
    68 	CList(TInt aCount, ...);
       
    69 	virtual ~CList();
       
    70 	inline TInt Count() const { return iCount; }
       
    71 	const T* Entries() const { return iEntries; }
       
    72 	const T& operator[](TInt aIndex) const;
       
    73 protected:
       
    74 	void Set(TInt aCount, VA_LIST aList);
       
    75 private:
       
    76 	const CList<T>& operator=(const CList<T>&);
       
    77 	TInt iCount;
       
    78 	T* iEntries;
       
    79 	};
       
    80 
       
    81 template <class T>
       
    82 CList<T>::CList()
       
    83 	: iCount(0), iEntries(NULL)
       
    84 	{
       
    85 	__ASSERT_COMPILE(sizeof(T) % sizeof(TUint32) == 0);
       
    86 	}
       
    87 
       
    88 template <class T>
       
    89 CList<T>::CList(TInt aCount, ...)
       
    90 	: iCount(aCount)
       
    91 	{
       
    92 	VA_LIST list;
       
    93 	VA_START(list, aCount);
       
    94 	Set(aCount, list);
       
    95 	}
       
    96 
       
    97 template <class T>
       
    98 CList<T>::~CList()
       
    99 	{
       
   100 	User::Free(iEntries);
       
   101 	iEntries = NULL;
       
   102 	}
       
   103 
       
   104 template <class T>
       
   105 void CList<T>::Set(TInt aCount, VA_LIST aList)
       
   106 	{
       
   107 	iCount = aCount;
       
   108 	test(iEntries == NULL);
       
   109 	iEntries = (T*)User::Alloc(sizeof(T) * iCount);
       
   110 	test_notNull(iEntries);
       
   111 	TInt argCount = iCount * (sizeof(T) / sizeof(TUint32));
       
   112 	for (TInt i = 0 ; i < argCount ; ++i)
       
   113 		((TUint32*)iEntries)[i] = VA_ARG(aList, TUint32);
       
   114 	}
       
   115 
       
   116 template <class T>
       
   117 const T& CList<T>::operator[](TInt aIndex) const
       
   118 	{
       
   119 	test(aIndex < iCount);
       
   120 	return iEntries[aIndex];
       
   121 	}
       
   122 
       
   123 /// Holds all the data associated with the user-side representation of a block map
       
   124 class CBlockMap : public CList<TBlockMapEntryBase>
       
   125 	{
       
   126 public:
       
   127 	CBlockMap(TUint aBlockGranularity,
       
   128 			  TUint aBlockStartOffset,
       
   129 			  TInt64 aStartBlockAddress,
       
   130 			  TUint aReadUnitShift,
       
   131 			  TUint aCodeLengthInFile,
       
   132 			  TUint aEntriesSize,
       
   133 			  ...);
       
   134 	inline const SBlockMapInfoBase& Info() const { return iInfo; }
       
   135 	inline TInt ReadUnitShift() const { return iReadUnitShift; }
       
   136 	inline TInt CodeLengthInFile() const { return iCodeLengthInFile; }
       
   137 	inline TInt EntriesSize() const { return iEntriesSize; }
       
   138 private:
       
   139 	SBlockMapInfoBase iInfo;
       
   140 	TBlockMapEntryBase* iEntries;
       
   141 	TUint iReadUnitShift;
       
   142 	TUint iCodeLengthInFile;
       
   143 	TUint iEntriesSize;
       
   144 	};
       
   145 
       
   146 CBlockMap::CBlockMap(TUint aBlockGranularity,
       
   147 					 TUint aBlockStartOffset,
       
   148 					 TInt64 aStartBlockAddress,
       
   149 					 TUint aReadUnitShift,
       
   150 					 TUint aCodeLengthInFile,
       
   151 					 TUint aEntriesSize,
       
   152 					 ...)
       
   153 	{
       
   154 	iInfo.iBlockGranularity = aBlockGranularity;
       
   155 	iInfo.iBlockStartOffset = aBlockStartOffset;
       
   156 	iInfo.iStartBlockAddress = aStartBlockAddress;
       
   157 	// don't care about iInfo.iLocalDriveNumber for test purposes
       
   158 	iReadUnitShift = aReadUnitShift;
       
   159 	iCodeLengthInFile = aCodeLengthInFile;
       
   160 	iEntriesSize = aEntriesSize;
       
   161 	iEntries = (TBlockMapEntryBase*)User::Alloc(iEntriesSize);
       
   162 
       
   163 	VA_LIST list;
       
   164 	VA_START(list, aEntriesSize);
       
   165 	Set(iEntriesSize / sizeof(TBlockMapEntryBase), list);
       
   166 	}
       
   167 
       
   168 /// A list of extents, for comparison with those generated by the kernel block map processing code
       
   169 class CExtentList : public CList<TBlockMap::SExtent>
       
   170 	{
       
   171 public:
       
   172 	typedef TBlockMap::SExtent SExtent;
       
   173 	CExtentList(TInt aCount, ...);
       
   174 	void Dump() const;
       
   175 	};
       
   176 
       
   177 CExtentList::CExtentList(TInt aCount, ...)
       
   178 	{
       
   179 	VA_LIST list;
       
   180 	VA_START(list, aCount);
       
   181 	Set(aCount, list);
       
   182 	}
       
   183 
       
   184 void CExtentList::Dump() const
       
   185 	{
       
   186 	RDebug::Printf("CExtentList:\n");
       
   187 	const CExtentList& self = *this;
       
   188 	for (TInt i = 0 ; i < Count() ; ++i)
       
   189 		RDebug::Printf("  %d: %08x -> %08x: %08x\n", i, self[i].iDataOffset, self[i+1].iDataOffset, self[i].iBlockNumber);
       
   190 	}
       
   191 
       
   192 TBool operator==(const TBlockMap::SExtent& a, const TBlockMap::SExtent& b)
       
   193 	{
       
   194 	return a.iDataOffset == b.iDataOffset && a.iBlockNumber == b.iBlockNumber;
       
   195 	}
       
   196 
       
   197 TBool operator!=(const TBlockMap::SExtent& a, const TBlockMap::SExtent& b)
       
   198 	{
       
   199 	return !(a == b);
       
   200 	}
       
   201 
       
   202 TBool CompareExtentsEqual(const TBlockMap& aBlockMap, const CExtentList& aExtentList)
       
   203 	{
       
   204 	if (aBlockMap.Count() != aExtentList.Count())
       
   205 		return EFalse;
       
   206 	for (TInt i = 0 ; i < aBlockMap.Count() ; ++i)
       
   207 		{
       
   208 		if (aBlockMap.Extent(i) != aExtentList[i])
       
   209 			return EFalse;
       
   210 		}
       
   211 	return ETrue;
       
   212 	}
       
   213 
       
   214 TInt MakeKernBlockMap(TBlockMap& aKbm, const CBlockMap& aUbm)
       
   215 	{
       
   216 	TBlockMapEntryBase* buffer = (TBlockMapEntryBase*)User::Alloc(aUbm.EntriesSize());
       
   217 	test_notNull(buffer);
       
   218 	Mem::Copy(buffer, aUbm.Entries(), aUbm.EntriesSize());
       
   219 	return aKbm.Initialise(aUbm.Info(),
       
   220 						   buffer,
       
   221 						   aUbm.EntriesSize(),
       
   222 						   aUbm.ReadUnitShift(),
       
   223 						   aUbm.CodeLengthInFile());
       
   224 }
       
   225 
       
   226 void MakeKernBlockMapAndTestExtents(const CBlockMap& aUbm, const CExtentList& aExpectedExtentList)
       
   227 	{
       
   228 	TBlockMap kbm;
       
   229 	test_noError(MakeKernBlockMap(kbm, aUbm));
       
   230 	TBool equal = CompareExtentsEqual(kbm, aExpectedExtentList);
       
   231 	if (!equal)
       
   232 		{
       
   233 		aExpectedExtentList.Dump();
       
   234 #ifdef _DEBUG
       
   235 		kbm.Dump();
       
   236 #endif
       
   237 		}
       
   238 	test(equal);
       
   239 	}
       
   240 
       
   241 // Tests
       
   242 
       
   243 void TestInitialiseErrors()
       
   244 	{
       
   245 	test.Next(_L("Test Initialise error checking"));
       
   246 	TBlockMap kbm;
       
   247 
       
   248 	// Block size must be a power of two
       
   249 	test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(513, 0, 0, 9, 1, 8, 1, 0)));
       
   250 
       
   251 	// Block size must be greater than or equal to the read unit size
       
   252 	test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 10, 1, 8, 1, 0)));
       
   253 
       
   254 	// Block start offset must be less than or equal to block size
       
   255 	test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 513, 0, 9, 1, 8, 1, 0)));
       
   256 
       
   257 	// Block zero address must be a multiple of the block size
       
   258 	test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 1, 9, 1, 8, 1, 0)));
       
   259 
       
   260 	// Code length in file must be greater than zero
       
   261 	test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 0, 8, 1, 0)));
       
   262 
       
   263 	// Size of entries array must be multiple of the size of one entry
       
   264 	test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 1, 9, 1, 0)));
       
   265 
       
   266 	// Size of entries must be non-zero
       
   267 	test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 1, 0)));
       
   268 	
       
   269 	// Size of block map must be greater or equal to size of data in file
       
   270 	test_equal(KErrArgument, MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 513, 8, 1, 0)));
       
   271 	}
       
   272 
       
   273 	// blockGranularity, startOffset, blockZeroAddress, readUnitShift, codeLengthInFile, entriesSize, (numberOfBlocks, startBlock)+
       
   274 
       
   275 void TestExtentList()
       
   276 	{
       
   277 	test.Next(_L("Test processing of user-side block map into extent list"));
       
   278 
       
   279 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   280 	//  |=      |       |       |       |       |       |       |       |       |
       
   281 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   282 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 0, 0, 9, 1, 8, 1, 0),
       
   283 								   CExtentList(1, 0, 0));
       
   284 
       
   285 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   286 	//  |       |=      |       |       |       |       |       |       |       |
       
   287 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   288 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 0, 512, 9, 1, 8, 1, 0),
       
   289 								   CExtentList(1, 0, 1));
       
   290 	
       
   291 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   292 	//  |       | =     |       |       |       |       |       |       |       |
       
   293 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   294 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1, 8, 1, 0),
       
   295 								   CExtentList(1, -23, 1));
       
   296 
       
   297 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   298 	//  |       |       |       | =     |       |       |       |       |       |
       
   299 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   300 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1, 8, 1, 2),
       
   301 								   CExtentList(1, -23, 3));
       
   302 
       
   303 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   304 	//  |       |       |       | ======|       |       |       |       |       |
       
   305 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   306 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 489, 8, 1, 2),
       
   307 								   CExtentList(1, -23, 3));
       
   308 
       
   309 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   310 	//  |       |       |       | ========      |       |       |       |       |
       
   311 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   312 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 600, 8, 2, 2),
       
   313 								   CExtentList(1, -23, 3));
       
   314 	
       
   315 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   316 	//  |       |       |       | ==============|       |==     |       |       |
       
   317 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   318 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1100, 16, 2, 2, 1, 5),
       
   319 								   CExtentList(2, -23, 3, 1001, 6));
       
   320 
       
   321 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   322 	//  |       |       |       | ==============|       |=======|       |       |
       
   323 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   324 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1513, 16, 2, 2, 1, 5),
       
   325 								   CExtentList(2, -23, 3, 1001, 6));
       
   326 	
       
   327 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   328 	//  |       |       |       | ==============|       |=======|=      |       |
       
   329 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   330 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 9, 1540, 16, 2, 2, 2, 5),
       
   331 								   CExtentList(2, -23, 3, 1001, 6));
       
   332 	}
       
   333 
       
   334 void TestExtentListScaled()
       
   335 	{
       
   336 	test.Next(_L("Test processing of user-side block map into extent list, block size > read unit size"));
       
   337 
       
   338 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   339 	//  |=  :   |   :   |   :   |   :   |   :   |   :   |   :   |   :   |   :   |
       
   340 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   341 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 0, 0, 8, 1, 8, 1, 0),
       
   342 								   CExtentList(1, 0, 0));
       
   343 
       
   344 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   345 	//  |   :   |=  :   |   :   |   :   |   :   |   :   |   :   |   :   |   :   |
       
   346 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   347 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 0, 512, 8, 1, 8, 1, 0),
       
   348 								   CExtentList(1, 0, 2));
       
   349 	
       
   350 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   351 	//  |   :   | = :   |   :   |   :   |   :   |   :   |   :   |   :   |   :   |
       
   352 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   353 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 23, 512, 8, 1, 8, 1, 0),
       
   354 								   CExtentList(1, -23, 2));
       
   355 
       
   356 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   357 	//  |   :   |   : = |   :   |   :   |   :   |   :   |   :   |   :   |   :   |
       
   358 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   359 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 1, 8, 1, 0),
       
   360 								   CExtentList(1, -24, 3));
       
   361 
       
   362 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   363 	//  |   :   |   :   |   :   |   : = |   :   |   :   |   :   |   :   |   :   |
       
   364 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   365 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 1, 8, 1, 2),
       
   366 								   CExtentList(1, -24, 7));
       
   367 
       
   368 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   369 	//  |   :   |   :   |   :   |   : ==|   :   |   :   |   :   |   :   |   :   |
       
   370 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   371 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 232, 8, 1, 2),
       
   372 								   CExtentList(1, -24, 7));
       
   373 
       
   374 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   375 	//  |   :   |   :   |   :   |   : ====  :   |   :   |   :   |   :   |   :   |
       
   376 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   377 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 333, 8, 2, 2),
       
   378 								   CExtentList(1, -24, 7));
       
   379 
       
   380 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   381 	//  |   :   |   :   |   :   |   : ========  |   :   |   :   |   :   |   :   |
       
   382 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   383 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 666, 8, 2, 2),
       
   384 								   CExtentList(1, -24, 7));
       
   385 
       
   386 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   387 	//  |   :   |   :   |   :   |   : ==========|   :   |   :   |   :   |   :   |
       
   388 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   389 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 744, 8, 2, 2),
       
   390 								   CExtentList(1, -24, 7));
       
   391 
       
   392 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   393 	//  |   :   |   :   |   :   |   : ==========|   :   |== :   |   :   |   :   |
       
   394 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   395 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 888, 16, 2, 2, 1, 5),
       
   396 								   CExtentList(2, -24, 7, 744, 12));
       
   397 
       
   398 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   399 	//  |   :   |   :   |   :   |   : ==========|   :   |=======|   :   |   :   |
       
   400 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   401 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 1256, 16, 2, 2, 1, 5),
       
   402 								   CExtentList(2, -24, 7, 744, 12));
       
   403 
       
   404 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   405 	//  |   :   |   :   |   :   |   : ==========|   :   |=========  :   |   :   |
       
   406 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   407 	MakeKernBlockMapAndTestExtents(CBlockMap(512, 280, 512, 8, 1350, 16, 2, 2, 2, 5),
       
   408 								   CExtentList(2, -24, 7, 744, 12));
       
   409 	}
       
   410 
       
   411 /// Holds the expected arguments for one call to the read function
       
   412 struct SReadEntry
       
   413 	{
       
   414 	TLinAddr iBuffer;
       
   415 	TInt iBlockNumber;
       
   416 	TInt iBlockCount;
       
   417 	};
       
   418 
       
   419 /// Holds a list of expected arguments for all calls to the read function
       
   420 class CReadInfo : public CList<SReadEntry>
       
   421 	{
       
   422 public:
       
   423 	CReadInfo(TInt aReturnVal, TInt aCount, ...);
       
   424 	const SReadEntry& Next();
       
   425 	void Done() const;
       
   426 	TInt ReturnVal() const { return iReturnVal; }
       
   427 private:
       
   428 	TInt iPos;
       
   429 	TInt iReturnVal;
       
   430 	};
       
   431 
       
   432 CReadInfo::CReadInfo(TInt aReturnVal, TInt aCount, ...)
       
   433 	: iPos(0), iReturnVal(aReturnVal)
       
   434 	{
       
   435 	VA_LIST list;
       
   436 	VA_START(list, aCount);
       
   437 	Set(aCount, list);
       
   438 	}
       
   439 
       
   440 const SReadEntry& CReadInfo::Next()
       
   441 	{
       
   442 	const CList<SReadEntry>& self = *this;
       
   443 	return self[iPos++];
       
   444 	}
       
   445 
       
   446 void CReadInfo::Done() const
       
   447 	{
       
   448 	test_equal(Count(), iPos);
       
   449 	}
       
   450 
       
   451 TInt ReadFunc(TAny* aArg, TAny*, TLinAddr aBuffer, TInt aBlockNumber, TInt aBlockCount)
       
   452 	{
       
   453 	CReadInfo& info = *(CReadInfo*)aArg;
       
   454 	const SReadEntry& expected = info.Next();
       
   455 	test_equal(expected.iBuffer, aBuffer);
       
   456 	test_equal(expected.iBlockNumber, aBlockNumber);
       
   457 	test_equal(expected.iBlockCount, aBlockCount);
       
   458 	return KErrNone;
       
   459 	}
       
   460 
       
   461 void TestRead(const TBlockMap& aBlockMap,
       
   462 			  TLinAddr aBuffer,
       
   463 			  TInt aPos,
       
   464 			  TInt aLength,
       
   465 			  TInt aReadUnitShift,
       
   466 			  const CReadInfo& aExpected)
       
   467 	{
       
   468 	test_equal(aExpected.ReturnVal(),
       
   469 			   aBlockMap.Read(aBuffer, aPos, aLength, aReadUnitShift, ReadFunc, (TAny*)&aExpected, (TAny*)NULL));
       
   470 	aExpected.Done();
       
   471 	}
       
   472 
       
   473 void TestReadErrors()
       
   474 	{
       
   475 	test.Next(_L("Test Read error checking"));
       
   476 
       
   477 	TBlockMap kbm, kbm2;
       
   478 	
       
   479 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   480 	//  |=      |       |       |       |       |       |       |       |       |
       
   481 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   482 	test_noError(MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 1, 8, 1, 0)));
       
   483 
       
   484 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   485 	//  |   :   |   :   |   :   |   : ==========|   :   |=========  :   |   :   |
       
   486 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------	
       
   487 	test_noError(MakeKernBlockMap(kbm2, CBlockMap(512, 280, 512, 8, 1350, 16, 2, 2, 2, 5)));
       
   488 
       
   489 	// Test read start position is outside block map
       
   490 	TestRead(kbm, 0, 1, 1, 9, CReadInfo(KErrArgument, 0));
       
   491 	TestRead(kbm2, 0, 1350, 1, 8, CReadInfo(KErrArgument, 0));
       
   492 
       
   493 	// Test read start position is negative
       
   494 	TestRead(kbm, 0, -1, 1, 9, CReadInfo(KErrArgument, 0));
       
   495 	TestRead(kbm2, 0, -1, 1, 8, CReadInfo(KErrArgument, 0));
       
   496 
       
   497 	// Test read length exceeds block map length 
       
   498 	TestRead(kbm, 0, 0, 2, 9, CReadInfo(KErrArgument, 1, 0, 0, 1));
       
   499 	TestRead(kbm2, 0, 1349, 2, 8, CReadInfo(KErrArgument, 1, 0, 14, 1));
       
   500 	}
       
   501 
       
   502 void TestReads()
       
   503 	{
       
   504 	test.Next(_L("Test Read"));
       
   505 
       
   506 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   507 	//  |=======================|       |       |       |       |       |       |
       
   508 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   509 	
       
   510 	TBlockMap kbm2;
       
   511 	test_noError(MakeKernBlockMap(kbm2, CBlockMap(512, 0, 0, 9, 1536, 8, 3, 0)));
       
   512 
       
   513 	// Test correct number of blocks read
       
   514 	TestRead(kbm2, 0, 0, 512, 9, CReadInfo(0, 1, 0, 0, 1));
       
   515 	TestRead(kbm2, 0, 0, 513, 9, CReadInfo(0, 1, 0, 0, 2));
       
   516 	TestRead(kbm2, 0, 0, 1024, 9, CReadInfo(0, 1, 0, 0, 2));
       
   517 	TestRead(kbm2, 0, 0, 1025, 9, CReadInfo(0, 1, 0, 0, 3));
       
   518 	TestRead(kbm2, 0, 0, 1536, 9, CReadInfo(0, 1, 0, 0, 3));
       
   519 
       
   520 	// Test start offset not aligned to read unit
       
   521 	TestRead(kbm2, 0, 1, 511, 9, CReadInfo(1, 1, 0, 0, 1));
       
   522 	TestRead(kbm2, 0, 256, 256, 9, CReadInfo(256, 1, 0, 0, 1));
       
   523 	TestRead(kbm2, 0, 511, 1, 9, CReadInfo(511, 1, 0, 0, 1));
       
   524 	TestRead(kbm2, 0, 513, 511, 9, CReadInfo(1, 1, 0, 1, 1));
       
   525 	TestRead(kbm2, 0, 1023, 1, 9, CReadInfo(511, 1, 0, 1, 1));
       
   526 
       
   527 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   528 	//  |=======|       |=======|       |=======|       |       |       |       |
       
   529 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   530 	
       
   531 	TBlockMap kbm;
       
   532 	test_noError(MakeKernBlockMap(kbm, CBlockMap(512, 0, 0, 9, 1536, 24, 1, 0, 1, 3, 1, 5)));
       
   533 
       
   534 	// Test correct block selected for read
       
   535 	TestRead(kbm, 0, 0, 1, 9, CReadInfo(0, 1, 0, 0, 1));
       
   536 	TestRead(kbm, 0, 256, 1, 9, CReadInfo(256, 1, 0, 0, 1));
       
   537 	TestRead(kbm, 0, 511, 1, 9, CReadInfo(511, 1, 0, 0, 1));
       
   538 	TestRead(kbm, 0, 512, 1, 9, CReadInfo(0, 1, 0, 3, 1));
       
   539 	TestRead(kbm, 0, 768, 1, 9, CReadInfo(256, 1, 0, 3, 1));
       
   540 	TestRead(kbm, 0, 1023, 1, 9, CReadInfo(511, 1, 0, 3, 1));
       
   541 	TestRead(kbm, 0, 1535, 1, 9, CReadInfo(511, 1, 0, 5, 1));
       
   542 
       
   543 	// Test reading multiple blocks
       
   544 	TestRead(kbm, 0, 0, 513, 9, CReadInfo(0, 2, 0, 0, 1, 512, 3, 1));
       
   545 	TestRead(kbm, 0, 0, 1024, 9, CReadInfo(0, 2, 0, 0, 1, 512, 3, 1));
       
   546 	TestRead(kbm, 0, 0, 1025, 9, CReadInfo(0, 3, 0, 0, 1, 512, 3, 1, 1024, 5, 1));
       
   547 	TestRead(kbm, 0, 0, 1536, 9, CReadInfo(0, 3, 0, 0, 1, 512, 3, 1, 1024, 5, 1));
       
   548 
       
   549 
       
   550 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   551 	//  |   ====|       |=======|       |=======|       |       |       |       |
       
   552 	//  +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------
       
   553 	
       
   554 	TBlockMap kbm3;
       
   555 	test_noError(MakeKernBlockMap(kbm3, CBlockMap(512, 256, 0, 9, 1280, 24, 1, 0, 1, 3, 1, 5)));
       
   556 
       
   557 	// Test correct block selected for read
       
   558 	TestRead(kbm3, 0, 0, 1, 9, CReadInfo(256, 1, 0, 0, 1));
       
   559 	TestRead(kbm3, 0, 255, 1, 9, CReadInfo(511, 1, 0, 0, 1));
       
   560 	TestRead(kbm3, 0, 256, 1, 9, CReadInfo(0, 1, 0, 3, 1));
       
   561 	TestRead(kbm3, 0, 767, 1, 9, CReadInfo(511, 1, 0, 3, 1));
       
   562 	TestRead(kbm3, 0, 768, 1, 9, CReadInfo(0, 1, 0, 5, 1));
       
   563 
       
   564 	// Test reading multiple blocks
       
   565 	TestRead(kbm3, 0, 0, 256, 9, CReadInfo(256, 1, 0, 0, 1));
       
   566 	TestRead(kbm3, 0, 0, 257, 9, CReadInfo(256, 2, 0, 0, 1, 512, 3, 1));
       
   567 	TestRead(kbm3, 0, 0, 768, 9, CReadInfo(256, 2, 0, 0, 1, 512, 3, 1));
       
   568 	TestRead(kbm3, 0, 0, 769, 9, CReadInfo(256, 3, 0, 0, 1, 512, 3, 1, 1024, 5, 1));
       
   569 	TestRead(kbm3, 0, 0, 1280, 9, CReadInfo(256, 3, 0, 0, 1, 512, 3, 1, 1024, 5, 1));
       
   570 	}
       
   571 
       
   572 TInt E32Main()
       
   573 	{
       
   574 	test.Title();
       
   575 	test.Start(_L("Unit tests the TKernBlockMap class"));
       
   576 
       
   577 	TestInitialiseErrors();
       
   578 	TestExtentList();
       
   579 	TestExtentListScaled();
       
   580 	TestReadErrors();
       
   581 	TestReads();
       
   582  
       
   583 	test.End();
       
   584 
       
   585 	return KErrNone;
       
   586 	}