kerneltest/e32test/mmu/t_codepaging.cpp
changeset 9 96e5fb8b040d
child 19 4a8fed1c0ef6
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_codepaging.cpp
       
    15 // This test relies on four dlls which it loads dynamically:
       
    16 // - t_codepaging_dll		Very simple dll, contains a single function.  Used for testing state
       
    17 // changes	of pages
       
    18 // - t_codepaging_dll2	 	Contains 8 pages of data, used for testing the correct data is paged
       
    19 // - t_codepaging_dll3		Statically links to t_codepaging_sll, used for testing ReadExportDir
       
    20 // - t_codepaging_dll4		Large dll, used for testing code segment that span more than one page
       
    21 // table
       
    22 // - t_codepaging_dll5		Contains relocatable const data.
       
    23 // - t_codepaging_dll6		Contains relocatable writable data.
       
    24 // - t_codepaging_dll7		Statically linked to t_codepaging_dll5 to check dependent DLLs
       
    25 // are initialised correctly.
       
    26 // Suite of tests specifically to test the code paging portion of demand 
       
    27 // paging.
       
    28 // 002 Exercise ReadExportDir with one code seg mapped already into current process
       
    29 // 003 Exercise ReadExportDir with one code seg mapped into different process
       
    30 // 004 Check locking of code which then gets unloaded
       
    31 // 004.01 Load test driver...
       
    32 // 004.02 Load/unload dll
       
    33 // 004.03 Load dll again
       
    34 // 004.04 Get data from DLL
       
    35 // 004.05 Lock DLL data
       
    36 // 004.06 Check DLL data
       
    37 // 004.07 Close DLL
       
    38 // 004.08 Check DLL loaded at different address
       
    39 // 004.09 Unlock DLL data
       
    40 // 004.10 Check DLL loaded at original address
       
    41 // 004.11 Cleanup
       
    42 // 005 Test writing to paged code
       
    43 // 005.01 Load DLL
       
    44 // 005.02 Get data from DLL
       
    45 // 005.03 Write to pages in DLL
       
    46 // 006 Running tests on drive I:
       
    47 // 007 Test accessing pages by executing code
       
    48 // 008 Test accessing pages by reading code
       
    49 // 009 Test accessing pages by reading code from another process via an alias
       
    50 // 010 Test unmapping paged code
       
    51 // 011 Test interactions between two processes
       
    52 // 012 Test that the contents of a paged DLL are as expected
       
    53 // 013 Test relocated const data in DLL
       
    54 // 014 Test relocated writable data in DLL
       
    55 // 015 Test relocated writable data in dependent DLL
       
    56 // 016 Test relocated writable data in preloaded dependent DLL
       
    57 // 017 Test relocated writable data in preloaded dependent DLL opened in other process
       
    58 // 018 Test killing a thread while it is taking paging faults
       
    59 // 019 Test unloading a library while another thread is executing it
       
    60 // 020 Test random access to a large dll
       
    61 // 021 Test accessing paged code from 2 processes at 1 priority level(s) for 5 seconds
       
    62 // 022 Test accessing paged code from 5 processes at 1 priority level(s) for 10 seconds
       
    63 // 023 Test accessing paged code from 10 processes at 1 priority level(s) for 20 seconds
       
    64 // 024 Test accessing paged code from 5 processes at 2 priority level(s) for 10 seconds
       
    65 // 025 Test accessing paged code from 50 processes at 1 priority level(s) for 2 seconds
       
    66 // 026 Running tests on drive Z:
       
    67 // 027 Test accessing pages by executing code
       
    68 // 028 Test accessing pages by reading code
       
    69 // 029 Test accessing pages by reading code from another process via an alias
       
    70 // 030 Test unmapping paged code
       
    71 // 031 Test interactions between two processes
       
    72 // 032 Test that the contents of a paged DLL are as expected
       
    73 // 033 Test relocated const data in DLL
       
    74 // 034 Test relocated writable data in DLL
       
    75 // 035 Test relocated writable data in dependent DLL
       
    76 // 036 Test relocated writable data in preloaded dependent DLL
       
    77 // 037 Test relocated writable data in preloaded dependent DLL opened in other process
       
    78 // 038 Test killing a thread while it is taking paging faults
       
    79 // 039 Test unloading a library while another thread is executing it
       
    80 // 040 Test random access to a large dll
       
    81 // 041 Test accessing paged code from 2 processes at 1 priority level(s) for 5 seconds
       
    82 // 042 Test accessing paged code from 5 processes at 1 priority level(s) for 10 seconds
       
    83 // 043 Test accessing paged code from 10 processes at 1 priority level(s) for 20 seconds
       
    84 // 044 Test accessing paged code from 5 processes at 2 priority level(s) for 10 seconds
       
    85 // 045 Test accessing paged code from 50 processes at 1 priority level(s) for 2 seconds
       
    86 // 
       
    87 //
       
    88 
       
    89 //! @SYMTestCaseID			KBASE-T_CODEPAGING-0335
       
    90 //! @SYMTestType			UT
       
    91 //! @SYMPREQ				PREQ1110
       
    92 //! @SYMTestCaseDesc		Demand Paging Code Paging tests.
       
    93 //! @SYMTestActions			001 Code paging tests
       
    94 //! @SYMTestExpectedResults All tests should pass.
       
    95 //! @SYMTestPriority        High
       
    96 //! @SYMTestStatus          Implemented
       
    97 
       
    98 
       
    99 #define __E32TEST_EXTENSION__
       
   100 #include <e32test.h>
       
   101 #include <f32file.h>
       
   102 #include <e32math.h>
       
   103 #include <dptest.h>
       
   104 
       
   105 #include "mmudetect.h"
       
   106 #include "d_memorytest.h"
       
   107 #include "d_demandpaging.h"
       
   108 #include "t_codepaging_dll.h"
       
   109 #include "paging_info.h"
       
   110 
       
   111 class TPagingDriveInfo
       
   112 	{
       
   113 public:
       
   114 	TChar iDriveLetter;
       
   115 	TDriveInfo iDriveInfo;
       
   116 	};
       
   117 
       
   118 RArray<TPagingDriveInfo> SupportedDrives;
       
   119 
       
   120 /// Page attributes, cut-n-paste'd from mmubase.h
       
   121 enum TType
       
   122 	{
       
   123 //	EInvalid=0,			// No physical RAM exists for this page
       
   124 //	EFixed=1,			// RAM fixed at boot time
       
   125 //	EUnused=2,			// Page is unused
       
   126 //	EChunk=3,
       
   127 //	ECodeSeg=4,
       
   128 //	EHwChunk=5,
       
   129 //	EPageTable=6,
       
   130 //	EPageDir=7,
       
   131 //	EPtInfo=8,
       
   132 //	EShadow=9,
       
   133 
       
   134 	EPagedROM=10,
       
   135 	EPagedCode=11,
       
   136 	EPagedData=12,
       
   137 	EPagedCache=13,
       
   138 	EPagedFree=14,
       
   139 	};
       
   140 
       
   141 enum TState
       
   142 	{
       
   143 	EStateNormal 			= 0,	// no special state
       
   144 	EStatePagedYoung 		= 1,
       
   145 	EStatePagedOld 			= 2,
       
   146 	EStatePagedDead 		= 3,	// Not possible on the flexible memory model.
       
   147 	EStatePagedLocked 		= 4,
       
   148 	EStatePagedOldestClean 	= 5,	// Flexible memory model only.
       
   149 	EStatePagedOldestDirty 	= 6,	// Flexible memory model only.
       
   150 	};
       
   151 
       
   152 
       
   153 
       
   154 /// The possible states for a logical page of RAM loaded code
       
   155 enum TPageState
       
   156 	{
       
   157 	EStateUnmapped,
       
   158 	EStatePagedOut,
       
   159 	EStateYoung,
       
   160 	EStateOld,
       
   161 	EStateOldestClean,
       
   162 	EStateOldestDirty,
       
   163 
       
   164 	ENumPageStates
       
   165 	};
       
   166 
       
   167 const TUint KPagedStateShift = 8;
       
   168 const TUint KPagedStateMask = 0xff00;
       
   169 
       
   170 
       
   171 /// The possible states for a physical page of RAM loaded code
       
   172 enum TPhysState
       
   173 	{
       
   174 	EPhysNotPresent,
       
   175 	EPhysYoung,
       
   176 	EPhysOld,
       
   177 	EPhysOldestClean,
       
   178 	EPhysOldestDirty,
       
   179 
       
   180 	ENumPhysStates
       
   181 	};
       
   182 
       
   183 /// Names of the logical page states
       
   184 const char* StateNames[ENumPageStates] =
       
   185 	{
       
   186 	"Unmapped",
       
   187 	"PagedOut",
       
   188 	"Young",
       
   189 	"Old",
       
   190 	"OldestClean",
       
   191 	"OldestDirty"
       
   192 	};
       
   193 
       
   194 /// Names of the physical page states
       
   195 const char* PhysStateNames[ENumPhysStates] =
       
   196 	{
       
   197 	"NotPresent",
       
   198 	"Young",
       
   199 	"Old",
       
   200 	"OldestClean",
       
   201 	"OldestDirty"
       
   202 	};
       
   203 
       
   204 /// Array of physical page states indexed by logical page state
       
   205 TPhysState PhysStateFromPageState[ENumPageStates] =
       
   206 	{
       
   207 	EPhysNotPresent,
       
   208 	EPhysNotPresent,
       
   209 	EPhysYoung,
       
   210 	EPhysOld,
       
   211 	EPhysOldestClean,
       
   212 	EPhysOldestDirty,
       
   213 	};
       
   214 
       
   215 /// The expected logical page state bitmask for each state
       
   216 TInt ExpectedPageState[ENumPageStates] =
       
   217 	{
       
   218 	0,
       
   219 	EPageStatePageTablePresent | EPageStateInRamCode | EPageStatePaged,
       
   220 	EPageStatePageTablePresent | EPageStateInRamCode | EPageStatePaged | EPageStatePtePresent | EPageStatePteValid,
       
   221 	EPageStatePageTablePresent | EPageStateInRamCode | EPageStatePaged | EPageStatePtePresent,
       
   222 	EPageStatePageTablePresent | EPageStateInRamCode | EPageStatePaged | EPageStatePtePresent,
       
   223 	EPageStatePageTablePresent | EPageStateInRamCode | EPageStatePaged | EPageStatePtePresent
       
   224 	};
       
   225 
       
   226 /// Extra bits we expect to be set on the multiple memory model
       
   227 TInt ExpectedPageStateMultipleExtra[ENumPageStates] =
       
   228 	{
       
   229 	EPageStateCodeChunkPresent,
       
   230 	EPageStateCodeChunkPresent,
       
   231 	EPageStateCodeChunkPresent | EPageStatePhysAddrPresent,
       
   232 	EPageStateCodeChunkPresent | EPageStatePhysAddrPresent
       
   233 	};
       
   234 
       
   235 /// Mask for the bits of the page state related to the physicsal page that we check
       
   236 TInt PhysStateMask = 0xffff;
       
   237 
       
   238 /// The expected physical page state bitmask for each state
       
   239 TInt ExpectedPhysState[ENumPhysStates] =
       
   240 	{
       
   241 	0,
       
   242 	EPagedCode | (EStatePagedYoung<<8),
       
   243 	EPagedCode | (EStatePagedOld<<8),
       
   244 	EPagedCode | (EStatePagedOldestClean<<8),
       
   245 	EPagedCode | (EStatePagedOldestDirty<<8)
       
   246 	};
       
   247 
       
   248 typedef void (*TFunc)(void);
       
   249 typedef void (*TFunc1)(TInt aArg1);
       
   250 typedef TFunc TTransitionTable[ENumPageStates][ENumPageStates];
       
   251 
       
   252 void LoadLibrary();
       
   253 void UnloadLibrary();
       
   254 void AccessPage();
       
   255 void MakeOld();
       
   256 void MakeOldest();
       
   257 void MakePagedOut();
       
   258 
       
   259 TTransitionTable StateTransitions =
       
   260 	{
       
   261 // Current:			Next:	EStateUnmapped	EStatePagedOut	EStateYoung		EStateOld	EStateOldestClean	EStateOldestDirty	
       
   262 /* EStateUnmapped 	*/	{	0,				LoadLibrary,	0,				0,			0,					0			},
       
   263 /* EStatePagedOut	*/	{	UnloadLibrary,	0,				AccessPage,		0,			0,					0			},
       
   264 /* EStateYoung		*/	{	UnloadLibrary,	MakePagedOut,	AccessPage,		MakeOld,	0,					0			},
       
   265 /* EStateOld		*/	{	UnloadLibrary,	MakePagedOut,	AccessPage,		0,			MakeOldest,			MakeOldest	},
       
   266 /* EStateOldestClean*/	{	UnloadLibrary,	MakePagedOut,	AccessPage,		0,			0,					0			},
       
   267 /* EStateOldestDirty*/	{	UnloadLibrary,	MakePagedOut,	AccessPage,		0,			0,					0			},
       
   268 	};
       
   269 
       
   270 const TInt KMaxPathLen = 16;
       
   271 typedef TPageState TStatePath[KMaxPathLen];
       
   272 
       
   273 // Test paths through the possible states that excercises all transitions except those back to unmapped
       
   274 // Doesn't consider dirty pages.
       
   275 TStatePath TestPathNoOldest =
       
   276 	{
       
   277 	EStateUnmapped,
       
   278 	EStatePagedOut,
       
   279 	EStateYoung,
       
   280 	EStateOld,
       
   281 	EStateYoung,
       
   282 	EStateOld,
       
   283 	EStatePagedOut,
       
   284 	EStateUnmapped,
       
   285 	};
       
   286 
       
   287 TStatePath TestPathOldest =
       
   288 	{
       
   289 	EStateUnmapped,
       
   290 	EStatePagedOut,
       
   291 	EStateYoung,
       
   292 	EStateOld,
       
   293 	EStateOldestClean,
       
   294 	EStateYoung,
       
   295 	EStateOld,
       
   296 	EStateYoung,
       
   297 	EStateOld,
       
   298 	EStatePagedOut,
       
   299 	EStateYoung,
       
   300 	EStateOld,
       
   301 	EStateOldestClean,
       
   302 	EStatePagedOut,
       
   303 	EStateUnmapped,
       
   304 	};
       
   305 
       
   306 TStatePath* TestPath = NULL;
       
   307 
       
   308 /// The different ways of accessing paged code
       
   309 enum TAccessMethod
       
   310 	{
       
   311 	EAccessExec,
       
   312 	EAccessRead,
       
   313 	EAccessAliasRead
       
   314 	};
       
   315 
       
   316 _LIT(KLibraryName, "t_codepaging_dll");
       
   317 _LIT(KSearchPathTemplate, "?:\\sys\\bin");
       
   318 
       
   319 // RTest stuff /////////////////////////////////////////////////////////////////
       
   320 
       
   321 RTest test(_L("T_CODEPAGING"));
       
   322 
       
   323 #define test_noError(x) { TInt _r = (x); if (_r < 0) HandleError(_r, __LINE__); }
       
   324 #define test_notNull(x) { TAny* _a = (TAny*)(x); if (_a == NULL) HandleNull(__LINE__); }
       
   325 #define test_equal(e, a) { TInt _e = TInt(e); TInt _a = TInt(a); if (_e != _a) HandleNotEqual(_e, _a, __LINE__); }
       
   326 
       
   327 void HandleError(TInt aError, TInt aLine)
       
   328 	{
       
   329 	test.Printf(_L("Error %d\n"), aError);
       
   330 	test.operator()(EFalse, aLine);
       
   331 	}
       
   332 
       
   333 void HandleNull(TInt aLine)
       
   334 	{
       
   335 	test.Printf(_L("Null value\n"));
       
   336 	test.operator()(EFalse, aLine);
       
   337 	}
       
   338 
       
   339 void HandleNotEqual(TInt aExpected, TInt aActual, TInt aLine)
       
   340 	{
       
   341 	test.Printf(_L("Expected 0x%x but got 0x%x\n"), aExpected, aActual);
       
   342 	test.operator()(EFalse, aLine);
       
   343 	}
       
   344 
       
   345 //  Server session /////////////////////////////////////////////////////////////
       
   346 
       
   347 _LIT(KServerName, "t_codepaging_server");
       
   348 
       
   349 class RTestSession : public RSessionBase
       
   350 	{
       
   351 public:
       
   352 	enum TMessage
       
   353 		{
       
   354 		EKill,
       
   355 		EExec,
       
   356 		ESetCurrentDrive,
       
   357 		EDesRead,
       
   358 		ETestPageState,
       
   359 		ETestStateTransition,
       
   360 		EStartRandomAccessThread
       
   361 		};
       
   362 public:
       
   363 	TInt Connect(TInt aProcessNum);
       
   364 	inline void Kill()
       
   365 		{ test_noError(RSessionBase::SendReceive(EKill,TIpcArgs())); }
       
   366 	inline void Exec(TFunc aFunc)
       
   367 		{ test_noError(RSessionBase::SendReceive(EExec,TIpcArgs((TInt)aFunc))); }
       
   368 	inline void SetCurrentDrive(TUint16 aDrive)
       
   369 		{ test_noError(RSessionBase::SendReceive(ESetCurrentDrive,TIpcArgs(aDrive))); }
       
   370 	inline void DesRead(const TDesC8& aData)
       
   371 		{ test_noError(RSessionBase::SendReceive(EDesRead,TIpcArgs(&aData))); }
       
   372 	inline void TestPageState(TPageState aState, TPhysState aPhysState)
       
   373 		{ test_noError(RSessionBase::SendReceive(ETestPageState,TIpcArgs(aState, aPhysState))); }
       
   374 	inline void TestStateTransition(TPageState aState)
       
   375 		{ test_noError(RSessionBase::SendReceive(ETestStateTransition,TIpcArgs(aState))); }
       
   376 	inline void StartRandomAccessThread(TThreadPriority aPriority)
       
   377 		{ test_noError(RSessionBase::SendReceive(EStartRandomAccessThread,TIpcArgs(aPriority))); }
       
   378 	};
       
   379 
       
   380 TInt RTestSession::Connect(TInt aProcessNum)
       
   381 	{
       
   382 	TBuf<32> name;
       
   383 	name.AppendFormat(_L("%S-%d"), &KServerName, aProcessNum);
       
   384 	return CreateSession(name,TVersion());
       
   385 	}
       
   386 
       
   387 
       
   388 // Global data /////////////////////////////////////////////////////////////////
       
   389 
       
   390 TBool MovingMemoryModel;
       
   391 TBool MultipleMemoryModel;
       
   392 TBool FlexibleMemoryModel;
       
   393 TBool HaveOldestLists;
       
   394 TInt ProcessNum;
       
   395 
       
   396 RTestSession OtherProcess;
       
   397 
       
   398 RLibrary PagedLibrary;
       
   399 TBool LibraryLoaded = EFalse;
       
   400 
       
   401 TTestFunction Library_TestFunction = NULL;
       
   402 
       
   403 TAccessMethod AccessMethod;
       
   404 
       
   405 RLibrary LargeLibrary;
       
   406 TBool LargeLibraryLoaded = EFalse;
       
   407 const TUint8* LargeDataStart;
       
   408 const TUint8* LargeDataEnd;
       
   409 const TUint8* LargeDataPtr;
       
   410 TInt PagesReadSinceLastAccess = 0;
       
   411 
       
   412 TInt LiveListSize;
       
   413 TInt PageSize;
       
   414 
       
   415 TPageState State;
       
   416 TPhysState PhysState;
       
   417 
       
   418 TUint16 CurrentDrive;
       
   419 TInt LocalDriveNumber;
       
   420 
       
   421 RThread RandomAccessThread;
       
   422 volatile TBool RandomAccessKill = EFalse;
       
   423 
       
   424 TBool CanForcePageOut = ETrue;
       
   425 
       
   426 // Utility functions ///////////////////////////////////////////////////////////
       
   427 
       
   428 TPtrC16 GetMediaType(TInt aMediaType)
       
   429 	{
       
   430 	_LIT(KMediaNotPresent, "MediaNotPresent");
       
   431 	_LIT(KMediaUnknown, "MediaUnknown");
       
   432 	_LIT(KMediaFloppy, "MediaFloppy");
       
   433 	_LIT(KMediaHardDisk, "MediaHardDisk");
       
   434 	_LIT(KMediaCdRom, "MediaCdRom");
       
   435 	_LIT(KMediaRam, "MediaRam");
       
   436 	_LIT(KMediaFlash, "MediaFlash");
       
   437 	_LIT(KMediaRom, "MediaRom");
       
   438 	_LIT(KMediaRemote, "MediaRemote");
       
   439 	_LIT(KMediaNANDFlash, "MediaNANDFlash");
       
   440 	_LIT(KMediaUnKnown, "MediaUnKnown");
       
   441 
       
   442 	switch(aMediaType)
       
   443 		{
       
   444 		case EMediaNotPresent:
       
   445 			return KMediaNotPresent();
       
   446 		case EMediaUnknown:
       
   447 			return KMediaUnknown();
       
   448 		case EMediaFloppy:
       
   449 			return KMediaFloppy();
       
   450 		case EMediaHardDisk:
       
   451 			return KMediaHardDisk();
       
   452 		case EMediaCdRom:
       
   453 			return KMediaCdRom();
       
   454 		case EMediaRam:
       
   455 			return KMediaRam();
       
   456 		case EMediaFlash:
       
   457 			return KMediaFlash();
       
   458 		case EMediaRom:
       
   459 			return KMediaRom();
       
   460 		case EMediaRemote:
       
   461 			return KMediaRemote();
       
   462 		case EMediaNANDFlash:
       
   463 			return KMediaNANDFlash();
       
   464 		default:
       
   465 			return KMediaUnKnown();
       
   466 		}
       
   467 	}
       
   468 
       
   469 // Get the list of pageable drives
       
   470 void GetSupportedDrives(TBool aVerbose = EFalse)
       
   471 	{
       
   472 	if (aVerbose)
       
   473 		{
       
   474 		test.Printf(_L("Supported drives:\n"));
       
   475 		test.Printf(_L("     Type             Attr     MedAttr  Filesystem\n"));
       
   476 		}
       
   477 		
       
   478 	RFs fs;
       
   479 	test_noError(fs.Connect());
       
   480 
       
   481 	TDriveList driveList;
       
   482 	TDriveInfo driveInfo;
       
   483 
       
   484 	TInt r = fs.DriveList(driveList);
       
   485     test_noError(r);
       
   486 
       
   487 	TBool NandPageableMediaFound = EFalse;
       
   488 
       
   489 	for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum)
       
   490 		{
       
   491 	    if(!driveList[drvNum])
       
   492 	        continue;   //-- skip unexisting drive
       
   493 	
       
   494 	    r = fs.Drive(driveInfo, drvNum);
       
   495 	    test_noError(r);
       
   496 
       
   497 
       
   498 		TChar ch;
       
   499 		r = fs.DriveToChar(drvNum, ch);
       
   500 		test_noError(r);
       
   501 
       
   502 		TBuf<256> fileSystemName;
       
   503 		r = fs.FileSystemName(fileSystemName, drvNum);
       
   504 		test_noError(r);
       
   505 	
       
   506 		if ((driveInfo.iDriveAtt & KDriveAttPageable) && (driveInfo.iType == EMediaNANDFlash))
       
   507 			NandPageableMediaFound = ETrue;
       
   508 
       
   509 		TBool pageable = EFalse;
       
   510 		if (driveInfo.iDriveAtt & KDriveAttPageable)
       
   511 			pageable = ETrue;
       
   512 
       
   513 		// If we've already found a pageable NAND drive, 
       
   514 		// then assume the Z: drive is pageable too if it's got a composite file system
       
   515 		_LIT(KCompositeName,"Composite");
       
   516 		if ((fileSystemName == KCompositeName()) && NandPageableMediaFound)
       
   517 			pageable = ETrue;
       
   518 			
       
   519 		if (pageable)
       
   520 			{
       
   521 			TChar ch;
       
   522 			r = fs.DriveToChar(drvNum, ch);
       
   523 			test_noError(r);
       
   524 
       
   525 			TPagingDriveInfo pagingDriveInfo;
       
   526 			pagingDriveInfo.iDriveLetter = ch;
       
   527 			pagingDriveInfo.iDriveInfo = driveInfo;
       
   528 
       
   529 			r = SupportedDrives.Append(pagingDriveInfo);
       
   530 			test_noError(r);
       
   531 			}
       
   532 		
       
   533 		if (aVerbose)
       
   534 			{
       
   535 			TPtrC16 mediaType = GetMediaType(driveInfo.iType);
       
   536 			_LIT(KPageable, "pageable");
       
   537 			test.Printf(_L("  %c: %16S %08x %08x %10S %S\n"), 
       
   538 						(TInt) ch, &mediaType, driveInfo.iDriveAtt, driveInfo.iMediaAtt,
       
   539 						&fileSystemName, (pageable ? &KPageable : &KNullDesC));
       
   540 			}
       
   541 		
       
   542 		}
       
   543 
       
   544 	fs.Close();
       
   545 	}
       
   546 
       
   547 TInt GetPageState(TAny* aPage)
       
   548 	{
       
   549 	TInt r = UserSvr::HalFunction(EHalGroupVM, EVMPageState, aPage, 0);
       
   550 	test_noError(r);
       
   551 	return r;
       
   552 	}
       
   553 
       
   554 // Force a page to be paged in or rejuvenated, to simulate aging of pages in the live list
       
   555 void ForcePageIn()
       
   556 	{
       
   557 	// Find a page that's old or paged out
       
   558 	do
       
   559 		{
       
   560 		LargeDataPtr += PageSize;
       
   561 		if (LargeDataPtr >= LargeDataEnd)
       
   562 			LargeDataPtr = LargeDataStart;
       
   563 		}
       
   564 	while (GetPageState((TAny*)LargeDataPtr) & EPageStatePteValid);
       
   565 
       
   566 	// and read from it to make it young
       
   567 	TUint32 value = *(volatile TUint8*)LargeDataPtr;
       
   568 	(void)value;
       
   569 	++PagesReadSinceLastAccess;
       
   570 	}
       
   571 
       
   572 void FlushAllPages()
       
   573 	{
       
   574 	test_noError(UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0));
       
   575 	}
       
   576 
       
   577 void TestCurrentState()
       
   578 	{
       
   579 	test_Value(State, State >= 0 && State < ENumPageStates);
       
   580 	test_Value(PhysState, PhysState >= 0 && PhysState < ENumPhysStates);
       
   581 	
       
   582 	TInt stateBits = GetPageState((TAny*)Library_TestFunction);
       
   583 	TInt expected = ExpectedPageState[State];
       
   584 	if (MultipleMemoryModel)
       
   585 		expected |= ExpectedPageStateMultipleExtra[State];
       
   586 	TUint physStateIgnore = 0;
       
   587 	if (FlexibleMemoryModel)
       
   588 		{
       
   589 		expected &= ~EPageStatePageTablePresent; // flexible memory model allocates page tables on demand
       
   590 		physStateIgnore = 0xff; // flexible memory model doesn't have separate page types for code/data/ROM
       
   591 		}
       
   592 
       
   593 	test_equal(expected, stateBits & (~PhysStateMask))
       
   594 	test_equal(ExpectedPhysState[PhysState] & ~physStateIgnore, stateBits & PhysStateMask & ~physStateIgnore)
       
   595 	}
       
   596 
       
   597 void TestPageState(TPageState aExpected, TPhysState aExpectedPhys)
       
   598 	{
       
   599 	RDebug::Printf("%d:  %-12s %-12s", ProcessNum, StateNames[aExpected], PhysStateNames[aExpectedPhys]);
       
   600 	test_equal(State, aExpected);
       
   601 	test_equal(PhysState, aExpectedPhys);
       
   602 	TestCurrentState();
       
   603 	}
       
   604 
       
   605 TInt PathLength(const TStatePath& aPath)
       
   606 	{
       
   607 	TInt i = 1;
       
   608 	while (aPath[i] != EStateUnmapped && i < KMaxPathLen)
       
   609 		++i;
       
   610 	return i + 1;
       
   611 	}
       
   612 
       
   613 TInt FindState(const TStatePath& aPath, TPageState aTarget)
       
   614 	{
       
   615 	TInt len = PathLength(aPath);
       
   616 	TInt j;
       
   617 	for (j = 1 ; j < len ; ++j)
       
   618 		{
       
   619 		if (aPath[j] == aTarget)
       
   620 			return j;
       
   621 		}
       
   622 	return -1;
       
   623 	}
       
   624 
       
   625 TInt WriteByte(TAny* aArg)
       
   626 	{
       
   627 	TUint8* ptr = (TUint8*)aArg;
       
   628 	*ptr = 23;
       
   629 	return KErrNone;
       
   630 	}
       
   631 
       
   632 void StartOtherProcess(TInt aProcessNum, RTestSession& aSession)
       
   633 	{
       
   634 	RProcess me, other;
       
   635 	TBuf<16> arg;
       
   636 	arg.AppendNum(aProcessNum);
       
   637 	test_noError(other.Create(me.FileName(), arg));
       
   638 	TRequestStatus status;
       
   639 	other.Rendezvous(status);
       
   640 	other.Resume();
       
   641 	User::WaitForRequest(status);
       
   642 	test_noError(status.Int());
       
   643 	test_equal(EExitPending, other.ExitType());
       
   644 	test_noError(aSession.Connect(aProcessNum));
       
   645 	other.Close();
       
   646 	}
       
   647 
       
   648 const TDesC& LibrarySearchPath(TUint16 aDrive)
       
   649 	{
       
   650 	static TBuf<32> path;
       
   651 	path = KSearchPathTemplate;
       
   652 	path[0] = aDrive;
       
   653 	return path;
       
   654 	}
       
   655 
       
   656 const TDesC& LibraryName(TInt aLibraryNum, TUint16 aDrive)
       
   657 	{
       
   658 	// this gives dlls a different name on each drive so we can be sure we're loading the right one
       
   659 	static TBuf<32> name;
       
   660 	name = KLibraryName;
       
   661 	if (aLibraryNum > 1)
       
   662 		name.AppendNum(aLibraryNum);
       
   663 	if (aDrive != 'Z')
       
   664 		name.AppendFormat(_L("_%c"), aDrive);
       
   665 	return name;
       
   666 	}
       
   667 
       
   668 const TDesC& LibraryFilename(TInt aLibraryNum, TUint16 aDrive)
       
   669 	{
       
   670 	static TBuf<40> filename;
       
   671 	filename = LibrarySearchPath(aDrive);
       
   672 	filename.AppendFormat(_L("\\%S.dll"), &LibraryName(aLibraryNum, aDrive));
       
   673 	return filename;
       
   674 	}
       
   675 
       
   676 TInt LoadSpecificLibrary(RLibrary& aLibrary, TInt aLibraryNum, TUint16 aDrive)
       
   677 	{
       
   678 	const TDesC& name = LibraryName(aLibraryNum, aDrive);
       
   679 	const TDesC& path = LibrarySearchPath(aDrive);
       
   680 	return aLibrary.Load(name, path);
       
   681 	}
       
   682 
       
   683 TInt GetLocDrvNumber(TUint16 aDrive)
       
   684 	{
       
   685 	RFs fs;
       
   686 	RFile file;
       
   687 
       
   688 	TBuf<40> libname = LibraryFilename(1, aDrive);
       
   689 	
       
   690 	fs.Connect();
       
   691 	TInt r=file.Open(fs,libname,EFileRead);
       
   692 	if(r!=KErrNone)
       
   693 		test.Printf(_L("%d: Error %d: could not open file %S\n"),ProcessNum, r, &libname);
       
   694 	test(r==KErrNone);
       
   695 
       
   696 	SBlockMapInfo info;
       
   697 	TInt64 start=0;
       
   698 	r=file.BlockMap(info,start, -1,ETestDebug);
       
   699 
       
   700 	if (r!=KErrNone && r!=KErrCompletion)
       
   701 		test.Printf(_L("Error %d: could not obtain block map\n"),r);
       
   702 	test(r==KErrNone || r==KErrCompletion);
       
   703 	TInt locDriveNumber=info.iLocalDriveNumber;
       
   704 
       
   705 	file.Close();
       
   706 	fs.Close();
       
   707 	return locDriveNumber;
       
   708 	}
       
   709 
       
   710 void LoadLargeLibrary()
       
   711 	{
       
   712 	test(!LargeLibraryLoaded);
       
   713 	test_noError(LoadSpecificLibrary(LargeLibrary, 4, CurrentDrive));
       
   714 	TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)LargeLibrary.Lookup(KGetAddressOfDataFunctionOrdinal);
       
   715 	TInt size;
       
   716 	LargeDataStart = (TUint8*)func(size);
       
   717 	test_notNull(LargeDataStart);
       
   718 	if (size < LiveListSize*PageSize)
       
   719 		{
       
   720 		// We need an area of paged data large enough to ensure we can cause a page of our choice to
       
   721 		// be paged out.  If the size of the live list for testing is too small, we'll skip some tests
       
   722 		CanForcePageOut = EFalse;
       
   723 		}
       
   724 	LargeDataEnd = LargeDataStart + size;
       
   725 	LargeDataPtr = LargeDataStart;
       
   726  	LargeLibraryLoaded = ETrue;
       
   727 	}
       
   728 
       
   729 void UnloadLargeLibrary()
       
   730 	{
       
   731 	test(LargeLibraryLoaded);
       
   732 	LargeLibrary.Close();
       
   733 	LargeDataStart = NULL;
       
   734 	LargeDataEnd = NULL;
       
   735 	LargeDataPtr = NULL;
       
   736 	LargeLibraryLoaded = EFalse;
       
   737 	}
       
   738 
       
   739 // Page in a page and keep aging it to see if it ever reaches an oldest list. 
       
   740 TBool SetHaveOldestLists()
       
   741 	{
       
   742 	AccessMethod = EAccessExec;
       
   743 	AccessPage();
       
   744 	TInt pagedState = (GetPageState((TAny*)Library_TestFunction) & KPagedStateMask) >> KPagedStateShift;
       
   745 	do	
       
   746 		{
       
   747 		ForcePageIn();
       
   748 		pagedState = (GetPageState((TAny*)Library_TestFunction) & KPagedStateMask) >> KPagedStateShift;
       
   749 		if (EStatePagedOldestClean == pagedState || EStatePagedOldestDirty == pagedState)
       
   750 			break;
       
   751 		}
       
   752 	while (	PagesReadSinceLastAccess <= LiveListSize);
       
   753 
       
   754 	HaveOldestLists = EStatePagedOldestClean == pagedState || EStatePagedOldestDirty == pagedState;
       
   755 	return HaveOldestLists;
       
   756 	}
       
   757 
       
   758 void SetCurrentDrive(TUint16 aDrive)
       
   759 	{
       
   760 	if (LargeLibraryLoaded)
       
   761 		UnloadLargeLibrary();
       
   762 	CurrentDrive = aDrive;
       
   763 	LocalDriveNumber = GetLocDrvNumber(aDrive);
       
   764 	LoadLargeLibrary();
       
   765 	if (!Library_TestFunction)
       
   766 		{
       
   767 		LoadLibrary();
       
   768 		Library_TestFunction = (TTestFunction)PagedLibrary.Lookup(KTestFunctionOrdinal);
       
   769 		test_notNull(Library_TestFunction);
       
   770 		if (SetHaveOldestLists())
       
   771 			TestPath = &TestPathOldest;
       
   772 		else
       
   773 			TestPath = &TestPathNoOldest;
       
   774 		UnloadLibrary();
       
   775 		FlushAllPages();
       
   776 		}
       
   777 	}
       
   778 
       
   779 // State transition functions //////////////////////////////////////////////////
       
   780 
       
   781 void LoadLibrary()
       
   782 	{
       
   783 	test_noError(LoadSpecificLibrary(PagedLibrary, 1, CurrentDrive));
       
   784 	if (MovingMemoryModel)
       
   785 		FlushAllPages(); // to make sure pages aren't already mapped
       
   786 	LibraryLoaded = ETrue;
       
   787 	}
       
   788 
       
   789 void UnloadLibrary()
       
   790 	{
       
   791 	PagedLibrary.Close();
       
   792 	LibraryLoaded = EFalse;
       
   793 	}
       
   794 
       
   795 void AccessPage()
       
   796 	{
       
   797 	switch (AccessMethod)
       
   798 		{
       
   799 		case EAccessExec:
       
   800 			Library_TestFunction();
       
   801 			break;
       
   802 
       
   803 		case EAccessRead:
       
   804 			{
       
   805 			TUint8 x = *(volatile TUint8*)Library_TestFunction;
       
   806 			(void)x;
       
   807 			}
       
   808 			break;
       
   809 
       
   810 		case EAccessAliasRead:
       
   811 			{
       
   812 			TPtrC8 des((TUint8*)Library_TestFunction, 4);  // descriptor header must be in different page to data
       
   813 			OtherProcess.DesRead(des);
       
   814 			}
       
   815 			break;
       
   816 
       
   817 		}
       
   818 	PagesReadSinceLastAccess = 0;
       
   819 	}
       
   820 
       
   821 void MakeOld()
       
   822 	{
       
   823 	TInt initialState = GetPageState((TAny*)Library_TestFunction);
       
   824 	do	
       
   825 		ForcePageIn();
       
   826 	while (PagesReadSinceLastAccess <= LiveListSize &&
       
   827 		   initialState == GetPageState((TAny*)Library_TestFunction));
       
   828 	TUint pagedState = (GetPageState((TAny*)Library_TestFunction) & KPagedStateMask) >> KPagedStateShift;
       
   829 	test_Equal(EStatePagedOld, pagedState);
       
   830 	}
       
   831 
       
   832 void MakeOldest()
       
   833 	{
       
   834 	TInt pagedState = (GetPageState((TAny*)Library_TestFunction) & KPagedStateMask) >> KPagedStateShift;
       
   835 	do	
       
   836 		{
       
   837 		ForcePageIn();
       
   838 		pagedState = (GetPageState((TAny*)Library_TestFunction) & KPagedStateMask) >> KPagedStateShift;
       
   839 		if (EStatePagedOldestClean == pagedState ||	EStatePagedOldestDirty == pagedState)
       
   840 			break;
       
   841 		}
       
   842 	while (PagesReadSinceLastAccess <= LiveListSize);
       
   843 	test_Value(pagedState, EStatePagedOldestClean == pagedState || EStatePagedOldestDirty == pagedState);
       
   844 	}
       
   845 
       
   846 void MakePagedOut()
       
   847 	{
       
   848 	TInt finalListState1 = EStatePagedOld;
       
   849 	TInt finalListState2 = EStatePagedOld;
       
   850 	if (HaveOldestLists)
       
   851 		{
       
   852 		finalListState1 = EStatePagedOldestClean;
       
   853 		finalListState2 = EStatePagedOldestDirty;
       
   854 		}
       
   855 
       
   856 	TInt pagedState = (GetPageState((TAny*)Library_TestFunction) & KPagedStateMask) >> KPagedStateShift;
       
   857 	// Get the page onto the final list(s) so it can be detected when it is paged out.
       
   858 	while (	pagedState != finalListState1 && pagedState != finalListState2 &&
       
   859 			PagesReadSinceLastAccess <= LiveListSize)
       
   860 		{
       
   861 		ForcePageIn();
       
   862 		pagedState = (GetPageState((TAny*)Library_TestFunction) & KPagedStateMask) >> KPagedStateShift;
       
   863 		}
       
   864 	// Now force the page off the paging lists.
       
   865 	pagedState = GetPageState((TAny*)Library_TestFunction);
       
   866 	do
       
   867 		{
       
   868 		ForcePageIn();
       
   869 		}
       
   870 	while (	PagesReadSinceLastAccess <= LiveListSize &&
       
   871 			pagedState == GetPageState((TAny*)Library_TestFunction));
       
   872 	}
       
   873 
       
   874 // Test functions //////////////////////////////////////////////////////////////
       
   875 
       
   876 void Initialise()
       
   877 	{
       
   878 	CurrentDrive = 'Z';
       
   879 	
       
   880 	TUint32 memModelAttrs = MemModelAttributes();
       
   881 	MovingMemoryModel = ((memModelAttrs & EMemModelTypeMask) == EMemModelTypeMoving);
       
   882 	MultipleMemoryModel = ((memModelAttrs & EMemModelTypeMask) == EMemModelTypeMultiple);
       
   883 	FlexibleMemoryModel = ((memModelAttrs & EMemModelTypeMask) == EMemModelTypeFlexible);
       
   884 
       
   885 	test_noError(UserSvr::HalFunction(EHalGroupKernel, EKernelHalPageSizeInBytes, &PageSize, 0));
       
   886 	
       
   887 	SVMCacheInfo info;
       
   888 	test_noError(UserSvr::HalFunction(EHalGroupVM, EVMHalGetCacheSize, &info, 0));
       
   889 	LiveListSize = info.iMaxSize / PageSize;
       
   890 	}
       
   891 
       
   892 void CopyDllFragmented(RFs& aFs, const TDesC& aSourceName, const TDesC& aDestName)
       
   893 	{
       
   894 	test.Printf(_L("  %S\n"), &aDestName);
       
   895 
       
   896 	TInt r = aFs.MkDirAll(aDestName);
       
   897 	test(r == KErrNone || r == KErrAlreadyExists);
       
   898 
       
   899 	TBuf<40> tempName(aDestName);
       
   900 	tempName.Append(_L(".tmp"));
       
   901 
       
   902 	RFile in, out, temp;
       
   903 	test_noError(in.Open(aFs, aSourceName, EFileRead));
       
   904 	test_noError(out.Replace(aFs, aDestName, EFileWrite));
       
   905 	test_noError(temp.Replace(aFs, tempName, EFileWrite));
       
   906 
       
   907 	const TInt KBufferSize = 3333;
       
   908 	TBuf8<KBufferSize> buffer;
       
   909 	
       
   910 	test_noError(temp.Write(buffer));
       
   911 	test_noError(temp.Flush());
       
   912 
       
   913 	TInt size;
       
   914 	test_noError(in.Size(size));
       
   915 	TInt pos = 0;
       
   916 	while (pos < size)
       
   917 		{
       
   918 		test_noError(in.Read(buffer));
       
   919 		test_noError(out.Write(buffer));
       
   920 		test_noError(out.Flush());
       
   921 		test_noError(temp.Write(buffer));
       
   922 		test_noError(temp.Flush());
       
   923 		pos += buffer.Length();
       
   924 		}
       
   925 	
       
   926 	in.Close();
       
   927 	out.Close();
       
   928 	temp.Close();
       
   929 	}
       
   930 
       
   931 void CopyDllToSupportedDrives(RFs& aFs, CFileMan* aFileMan, TInt aLibraryNum)
       
   932 	{
       
   933 	TBuf<40> source = LibraryFilename(aLibraryNum, 'Z');
       
   934 
       
   935 	test.Printf(_L("Copying %S to:\n"), &source);
       
   936 	
       
   937 	for (TInt i = 0 ; i < SupportedDrives.Count() ; ++i)
       
   938 		{
       
   939 		TUint8 drive = SupportedDrives[i].iDriveLetter;
       
   940 		if (!(SupportedDrives[i].iDriveInfo.iMediaAtt & KMediaAttWriteProtected))
       
   941 			{
       
   942 			TBuf<40> dest = LibraryFilename(aLibraryNum, drive);
       
   943 			CopyDllFragmented(aFs, source, dest);
       
   944 			}
       
   945 		}
       
   946 	}
       
   947 
       
   948 void CopyDllsToSupportedDrives()
       
   949 	{
       
   950 	RFs fs;
       
   951 	test_noError(fs.Connect());
       
   952 
       
   953 	CTrapCleanup* cleanup = CTrapCleanup::New();
       
   954 	test_notNull(cleanup);
       
   955 	
       
   956 	CFileMan* fileMan = NULL;
       
   957 	TRAPD(r, fileMan = CFileMan::NewL(fs));
       
   958 	test_noError(r);
       
   959 
       
   960 	for (TInt i = 1 ; i <= 7 ; ++i)
       
   961 		CopyDllToSupportedDrives(fs, fileMan, i);
       
   962 	
       
   963 	delete fileMan;
       
   964 	delete cleanup;	
       
   965 	fs.Close();
       
   966 	}
       
   967 
       
   968 void TestStateTransition(TPageState aNext)
       
   969 	{
       
   970 	TPhysState nextPhys = PhysStateFromPageState[aNext];
       
   971 	RDebug::Printf("%d:  %-12s            -> %-12s", ProcessNum, StateNames[State], StateNames[aNext]);
       
   972 	TFunc func = StateTransitions[State][aNext];
       
   973 	test_notNull(func);
       
   974 	func();
       
   975 	State = aNext;
       
   976 	PhysState = nextPhys;
       
   977 	TestCurrentState();
       
   978 	}
       
   979 
       
   980 void RunPathTest(const TStatePath& aPath, TInt aStart = 0, TInt aEnd = -1)
       
   981 	{
       
   982 	if (aEnd == -1)
       
   983 		aEnd = PathLength(aPath) - 1;
       
   984 
       
   985 	// Check we're already in the starting state
       
   986 	TestPageState(aPath[aStart], PhysStateFromPageState[aPath[aStart]]);
       
   987 
       
   988 	for (TInt i = aStart + 1 ; i <= aEnd ; ++i)
       
   989 		TestStateTransition(aPath[i]);
       
   990 	}
       
   991 
       
   992 void RunUnmapTest(const TStatePath& aPath)
       
   993 	{
       
   994 	TInt len = PathLength(aPath);
       
   995 	
       
   996 	// Test an unmodified code paged page can be unmapped from all the possible 
       
   997 	// states it can be in.
       
   998 	TInt endState = EStateOld;
       
   999 	if (HaveOldestLists)
       
  1000 		endState = EStateOldestClean;
       
  1001 		
       
  1002 	for (TInt i = EStateUnmapped + 1; i <= endState; ++i)
       
  1003 		{
       
  1004 		TPageState target = (TPageState)i;
       
  1005 		RDebug::Printf("\nUnmap from %s:\n", StateNames[target]);
       
  1006 
       
  1007 		TStatePath path;
       
  1008 		memcpy(path, aPath, sizeof(path));
       
  1009 
       
  1010 		TInt j = FindState(path, target) + 1;
       
  1011 		test_Value(j, j > 0 && j < len + 1);
       
  1012 		path[j] = EStateUnmapped;
       
  1013 		
       
  1014 		RunPathTest(path, 0, j);
       
  1015 		}
       
  1016 	}
       
  1017 
       
  1018 void GoToState(TPageState aState)
       
  1019 	{
       
  1020 	if (LibraryLoaded)
       
  1021 		{
       
  1022 		UnloadLibrary();
       
  1023 		State = EStateUnmapped;
       
  1024 		PhysState = PhysStateFromPageState[State];
       
  1025 		}
       
  1026 		
       
  1027 	TInt i = FindState(*TestPath, aState);
       
  1028 	test(i != -1);
       
  1029 	RunPathTest(*TestPath, 0, i);
       
  1030 	}
       
  1031 
       
  1032 void RunMultiProcessTest()
       
  1033 	{
       
  1034 	TStatePath& testPath = *TestPath;
       
  1035 	TInt len = PathLength(testPath);
       
  1036 	
       
  1037 	TInt endState = EStateOld;
       
  1038 	if (HaveOldestLists)
       
  1039 		endState = EStateOldestClean;
       
  1040 	for (TInt i = EStateUnmapped; i <= endState; ++i)
       
  1041 		{
       
  1042 		TPageState target = (TPageState)i;
       
  1043 		RDebug::Printf("\nTesting interaction with second process in state %s:\n", StateNames[target]);
       
  1044 		
       
  1045 		GoToState(target);
       
  1046 		TPageState state2 = testPath[0];  // current state in other process
       
  1047 		OtherProcess.TestPageState(state2, PhysStateFromPageState[state2]);
       
  1048 		for (TInt i = 1 ; i < len ; ++i)
       
  1049 			{
       
  1050 			TPageState next2 = testPath[i];
       
  1051 			OtherProcess.TestStateTransition(next2);
       
  1052 			
       
  1053 			// Update physical state if affected by transition in other process
       
  1054 			if ((State == EStateYoung || State == EStateOld || State == EStateOldestClean) &&
       
  1055 				(state2 != EStateUnmapped && next2 != EStateUnmapped))
       
  1056 				PhysState = PhysStateFromPageState[next2];
       
  1057 
       
  1058 			// Update logical state in this process if affected by transition in other process
       
  1059 			if (State == EStateYoung && next2 == EStateOld)
       
  1060 				State = EStateOld;
       
  1061 			else if (State == EStateOld && next2 == EStateOldestClean)
       
  1062 				State = EStateOldestClean;
       
  1063 			else if ((State == EStateYoung || State == EStateOld || State == EStateOldestClean) &&
       
  1064 					 (state2 == EStateOld  || state2 == EStateOldestClean) && next2 == EStatePagedOut)
       
  1065 				State = EStatePagedOut;
       
  1066 
       
  1067 			RDebug::Printf("%d:  %-12s %-12s", ProcessNum, StateNames[State], PhysStateNames[PhysState]);
       
  1068 			TestCurrentState();
       
  1069 			state2 = next2;
       
  1070 			}
       
  1071 		}
       
  1072 
       
  1073 	if (LibraryLoaded)
       
  1074 		{
       
  1075 		UnloadLibrary();
       
  1076 		State = EStateUnmapped;
       
  1077 		PhysState = PhysStateFromPageState[State];
       
  1078 		}	
       
  1079 	}
       
  1080 
       
  1081 void TestReadExportDir()
       
  1082 	{
       
  1083 	RLibrary library;
       
  1084 	test_noError(LoadSpecificLibrary(library, 3, CurrentDrive));
       
  1085 	TTestFunction func = (TTestFunction)library.Lookup(KTestFunctionOrdinal);
       
  1086 	test_notNull(func);
       
  1087 	test_noError(func());
       
  1088 	library.Close();
       
  1089 	}
       
  1090 
       
  1091 void RunReadExportDirTest()
       
  1092 	{
       
  1093 	test.Next(_L("Exercise ReadExportDir with one code seg mapped already into current process"));
       
  1094 	LoadLibrary();
       
  1095 	TestReadExportDir();
       
  1096 	UnloadLibrary();
       
  1097 
       
  1098 	test.Next(_L("Exercise ReadExportDir with one code seg mapped into different process"));
       
  1099 	OtherProcess.Exec(LoadLibrary);
       
  1100 	TestReadExportDir();
       
  1101 	OtherProcess.Exec(UnloadLibrary);
       
  1102 	}
       
  1103 
       
  1104 void RunWriteToPagedCodeTest()
       
  1105 	{
       
  1106 	test.Next(_L("Test writing to paged code"));
       
  1107 
       
  1108 	RMemoryTestLdd memoryTest;
       
  1109 	test(KErrNone==memoryTest.Open());
       
  1110 
       
  1111 	FlushAllPages();
       
  1112 	TUint8* ptr = (TUint8*)LargeDataStart;
       
  1113 	while(ptr<LargeDataEnd)
       
  1114 		{
       
  1115 		TInt stateBits = GetPageState(ptr);
       
  1116 		// write to paged out memory should cause exception...
       
  1117 		test(KErrBadDescriptor==memoryTest.WriteMemory(ptr,0));
       
  1118 		// page state should be unchanged...
       
  1119 		test_equal(stateBits,GetPageState(ptr))
       
  1120 		// page-in in memory...
       
  1121 		TUint32 value = *(TUint32*)ptr;
       
  1122 		// page state should be changed...
       
  1123 		test(stateBits!=GetPageState(ptr));
       
  1124 		// write to paged out memory should still cause exception...
       
  1125 		test(KErrBadDescriptor==memoryTest.WriteMemory(ptr,~value));
       
  1126 		// memory should be unchanged...
       
  1127 		test(value==*(TUint32*)ptr);
       
  1128 		ptr += PageSize;
       
  1129 		}
       
  1130 
       
  1131 	memoryTest.Close();
       
  1132 	}
       
  1133 
       
  1134 void RunPageLockingTest()
       
  1135 	{
       
  1136 	test.Next(_L("Check locking of code which then gets unloaded"));
       
  1137 
       
  1138 	// load test driver...
       
  1139 	test.Start(_L("Load test driver..."));
       
  1140 	RDemandPagingTestLdd ldd;
       
  1141 	TInt r = User::LoadLogicalDevice(KDemandPagingTestLddName);
       
  1142 	test(r==KErrNone || r==KErrAlreadyExists);
       
  1143 	test(ldd.Open()==KErrNone);
       
  1144 
       
  1145 	// load once to get address that code will be loaded at...
       
  1146 	test.Next(_L("Load/unload dll"));
       
  1147 	RLibrary library;
       
  1148 	test_noError(LoadSpecificLibrary(library, 5, CurrentDrive));
       
  1149 	TGetAddressOfRelocatedDataFunction func = (TGetAddressOfRelocatedDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal);
       
  1150 	test_notNull(func);
       
  1151 	library.Close();
       
  1152 
       
  1153 	// load again and check it's at the same place...
       
  1154 	test.Next(_L("Load dll again"));
       
  1155 	test_noError(LoadSpecificLibrary(library, 5, CurrentDrive));
       
  1156 	TGetAddressOfRelocatedDataFunction func2 = (TGetAddressOfRelocatedDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal);
       
  1157 	test_equal(func,func2);
       
  1158 
       
  1159 	// get address of data in the DLL...
       
  1160 	test.Next(_L("Get data from DLL"));
       
  1161 	void* d;
       
  1162 	void* c;
       
  1163 	TInt size;
       
  1164 	void** data = func(size,d,c);
       
  1165 
       
  1166 	// lock pages...
       
  1167 	test.Next(_L("Lock DLL data"));
       
  1168 	r = ldd.Lock(data,size);
       
  1169 	test_equal(r,1);
       
  1170 
       
  1171 	// check data...
       
  1172 	test.Next(_L("Check DLL data"));
       
  1173 	for (TInt i = 0 ; i < size / 4 ; i+=2)
       
  1174 		{
       
  1175 		test_equal(c, data[i]);
       
  1176 		test_equal(d, data[i+1]);
       
  1177 		}
       
  1178 
       
  1179 	// close library...
       
  1180 	test.Next(_L("Close DLL"));
       
  1181 	library.Close();
       
  1182 	User::After(1000000);
       
  1183 
       
  1184 	if(!FlexibleMemoryModel) // flexible memory model doesn't actually hog virtual address when locked (pinned)
       
  1185 		{
       
  1186 		// load again and check it's at a different place
       
  1187 		// (because the locked memory is hogging the old place)...
       
  1188 		test.Next(_L("Check DLL loaded at different address"));
       
  1189 		test_noError(LoadSpecificLibrary(library, 5, CurrentDrive));
       
  1190 		func2 = (TGetAddressOfRelocatedDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal);
       
  1191 		test(func!=func2);
       
  1192 		library.Close();
       
  1193 		User::After(1000000);
       
  1194 
       
  1195 		// unlock pages...
       
  1196 		test.Next(_L("Unlock DLL data"));
       
  1197 		r = ldd.Unlock();
       
  1198 		User::After(1000000);
       
  1199 
       
  1200 		// load again and check it's back at the original place
       
  1201 		// (because the locked memory now gone)...
       
  1202 		test.Next(_L("Check DLL loaded at original address"));
       
  1203 		test_noError(LoadSpecificLibrary(library, 5, CurrentDrive));
       
  1204 		func2 = (TGetAddressOfRelocatedDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal);
       
  1205 		test(func==func2);
       
  1206 		library.Close();
       
  1207 		}
       
  1208 
       
  1209 	// cleanup...
       
  1210 	test.Next(_L("Cleanup"));
       
  1211 	ldd.Close();
       
  1212 
       
  1213 	test.End();
       
  1214 	}
       
  1215 
       
  1216 void TestContentsOfPagedDll()
       
  1217 	{
       
  1218 	test.Next(_L("Test that the contents of a paged DLL are as expected"));
       
  1219 
       
  1220 	RLibrary library2;
       
  1221 	test_noError(LoadSpecificLibrary(library2, 2, CurrentDrive));
       
  1222 
       
  1223 	TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)library2.Lookup(KGetAddressOfDataFunctionOrdinal);
       
  1224 	test_notNull(func);
       
  1225 
       
  1226 	TInt size;
       
  1227 	TUint* data;
       
  1228 	data = func(size);
       
  1229 	test_notNull(data);
       
  1230 
       
  1231 	// Data contents are psuedorandom numbers generated according to the following scheme
       
  1232 	const TInt A = 1664525;
       
  1233 	const TInt B = 1013904223;
       
  1234 	TUint v = 23;
       
  1235 	for (TInt i = 0 ; i < size / 4 ; ++i)
       
  1236 		{
       
  1237 		v = A * v + B;
       
  1238 		test_equal(v, data[i]);
       
  1239 		}
       
  1240 
       
  1241 	library2.Close();
       
  1242 	}
       
  1243 
       
  1244 
       
  1245 void CheckRelocatableData(RLibrary& library)
       
  1246 	{
       
  1247 	TGetAddressOfRelocatedDataFunction func = (TGetAddressOfRelocatedDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal);
       
  1248 	test_notNull(func);
       
  1249 	void* d;
       
  1250 	void* c;
       
  1251 	TInt size;
       
  1252 	void** data = func(size,d,c);
       
  1253 	test_equal(d, data);
       
  1254 	for (TInt i = 0 ; i < size / 4 ; i+=2)
       
  1255 		{
       
  1256 		test_equal(c, data[i]);
       
  1257 		test_equal(d, data[i+1]);
       
  1258 		}
       
  1259 	}
       
  1260 
       
  1261 
       
  1262 void OtherProcessCheckRelocatableData()
       
  1263 	{
       
  1264 	RLibrary library;
       
  1265 	test_noError(LoadSpecificLibrary(library, 7, CurrentDrive));
       
  1266 	CheckRelocatableData(library);
       
  1267 	library.Close();
       
  1268 	}
       
  1269 
       
  1270 
       
  1271 void TestContentsOfPagedDllWithRelocatedData()
       
  1272 	{
       
  1273 	test.Next(_L("Test relocated const data in DLL"));
       
  1274 	PagingInfo::ResetBenchmarks();
       
  1275 	RLibrary library;
       
  1276 	test_noError(LoadSpecificLibrary(library, 5, CurrentDrive));
       
  1277 	CheckRelocatableData(library);
       
  1278 	library.Close();
       
  1279 	PagingInfo::PrintBenchmarks();	// worst case fixups
       
  1280 
       
  1281 	test.Next(_L("Test relocated writable data in DLL"));
       
  1282 	test_noError(LoadSpecificLibrary(library, 6, CurrentDrive));
       
  1283 	CheckRelocatableData(library);
       
  1284 	library.Close();
       
  1285 
       
  1286 	test.Next(_L("Test relocated writable data in dependent DLL"));
       
  1287 	test_noError(LoadSpecificLibrary(library, 7, CurrentDrive));
       
  1288 	CheckRelocatableData(library);
       
  1289 	library.Close();
       
  1290 
       
  1291 	test.Next(_L("Test relocated writable data in preloaded dependent DLL"));
       
  1292 	RLibrary library2;
       
  1293 	test_noError(LoadSpecificLibrary(library2, 6, CurrentDrive));
       
  1294 	test_noError(LoadSpecificLibrary(library, 7, CurrentDrive));
       
  1295 	CheckRelocatableData(library);
       
  1296 	library.Close();
       
  1297 	library2.Close();
       
  1298 
       
  1299 	test.Next(_L("Test relocated writable data in preloaded dependent DLL opened in other process"));
       
  1300 	test_noError(LoadSpecificLibrary(library2, 6, CurrentDrive));
       
  1301 	OtherProcess.Exec(OtherProcessCheckRelocatableData);
       
  1302 	library2.Close();
       
  1303 	}
       
  1304 
       
  1305 
       
  1306 TInt RandomAccessFunc(TAny* aArg)
       
  1307 	{
       
  1308 	const TUint8* dataStart = LargeDataStart;
       
  1309 	const TUint8* dataEnd = LargeDataEnd;	
       
  1310 	TInt size = dataEnd - dataStart;
       
  1311 	TUint32 random = (User::FastCounter() << 8) | ProcessNum;
       
  1312 	TInt i = 0;
       
  1313 	while (!RandomAccessKill)
       
  1314 		{
       
  1315 		random = random*69069+1;
       
  1316 		TInt offset = random % size;
       
  1317 		TInt value = dataStart[offset];
       
  1318 		if (offset != 0 && value != 0)
       
  1319 			return KErrGeneral;
       
  1320 		++i;
       
  1321 		}
       
  1322 
       
  1323 	RDebug::Printf("%d: Performed %d accesses", ProcessNum, i);
       
  1324 	return KErrNone;
       
  1325 	}
       
  1326 
       
  1327 void StartRandomAccessThread(TThreadPriority aPriority)
       
  1328 	{
       
  1329 	RandomAccessKill = EFalse;
       
  1330 	test_noError(RandomAccessThread.Create(_L("RandomAccessThread"), RandomAccessFunc, 4096, NULL, 0));
       
  1331 	RDebug::Printf("%d: starting thread with priority %d", ProcessNum, aPriority);
       
  1332 	RandomAccessThread.SetPriority(aPriority);
       
  1333 	RandomAccessThread.Resume();
       
  1334 	}
       
  1335 
       
  1336 void KillRandomAccessThread()
       
  1337 	{
       
  1338 	test_equal(EExitPending, RandomAccessThread.ExitType());
       
  1339 	TRequestStatus status;
       
  1340 	RandomAccessThread.Logon(status);
       
  1341 	RandomAccessKill = ETrue;
       
  1342 	User::WaitForRequest(status);
       
  1343 	test_equal(EExitKill, RandomAccessThread.ExitType());
       
  1344 	test_equal(0, RandomAccessThread.ExitReason());
       
  1345 	RandomAccessThread.Close();
       
  1346 	PagedLibrary.Close();
       
  1347 	}
       
  1348 
       
  1349 void TestLargeDll(TInt aDelay)
       
  1350 	{
       
  1351 	test.Next(_L("Test random access to a large dll"));
       
  1352 	StartRandomAccessThread(EPriorityLess);
       
  1353 	User::After(aDelay * 1000000);
       
  1354 	KillRandomAccessThread();
       
  1355 	}
       
  1356 
       
  1357 void TestKillThreadWhilePaging()
       
  1358 	{
       
  1359  	test.Next(_L("Test killing a thread while it is taking paging faults"));
       
  1360 	for (TInt i = 0 ; i < 50 ; ++i)
       
  1361 		{
       
  1362 		RDebug::Printf("  iteration %d", i);
       
  1363 		StartRandomAccessThread(EPriorityLess);
       
  1364 		User::After(10000);  // time for ~ 10 paging requests
       
  1365 		test_equal(EExitPending, RandomAccessThread.ExitType());
       
  1366 		TRequestStatus status;
       
  1367 		RandomAccessThread.Logon(status);
       
  1368 		RandomAccessThread.Terminate(666);
       
  1369 		User::WaitForRequest(status);
       
  1370 		test_equal(EExitTerminate, RandomAccessThread.ExitType());
       
  1371 		test_equal(666, RandomAccessThread.ExitReason());
       
  1372 		RandomAccessThread.Close();
       
  1373 		PagedLibrary.Close();
       
  1374 		}
       
  1375 	}
       
  1376 
       
  1377 void TestUnloadDllWhilePaging()
       
  1378 	{
       
  1379  	test.Next(_L("Test unloading a library while another thread is accessing it"));
       
  1380 	OtherProcess.Exec(UnloadLargeLibrary);
       
  1381 	for (TInt i = 0 ; i < 50 ; ++i)
       
  1382 		{
       
  1383 		RDebug::Printf("  iteration %d", i);
       
  1384 		StartRandomAccessThread(EPriorityLess);
       
  1385 		User::After(10000);  // time for ~ 10 paging requests
       
  1386 		test_equal(EExitPending, RandomAccessThread.ExitType());
       
  1387 		TRequestStatus status;
       
  1388 		RandomAccessThread.Logon(status);
       
  1389 		UnloadLargeLibrary();
       
  1390 		PagedLibrary.Close();
       
  1391 		User::WaitForRequest(status);
       
  1392 		test_equal(EExitPanic, RandomAccessThread.ExitType());
       
  1393 		test_equal(3, RandomAccessThread.ExitReason());  // KERN-EXEC 3
       
  1394 		RandomAccessThread.Close();
       
  1395 		LoadLargeLibrary();
       
  1396 		}
       
  1397 	OtherProcess.Exec(LoadLargeLibrary);
       
  1398 	}
       
  1399 
       
  1400 void PrintElapsedTime(TTime& aStartTime)
       
  1401 	{		
       
  1402 	TTime timeNow;
       
  1403 	timeNow.UniversalTime();
       
  1404 	TTimeIntervalSeconds elapsed;
       
  1405 	test_noError(timeNow.SecondsFrom(aStartTime, elapsed));
       
  1406 	test.Printf(_L("%d seconds elapsed\n"), elapsed.Int());
       
  1407 	}
       
  1408 
       
  1409 void TestManyProcesses(TInt aCount, TInt aDelay, TInt aPriorities = 1)
       
  1410 	{
       
  1411 	TBuf<128> name;
       
  1412 	name.AppendFormat(_L("Test accessing paged code from %d processes at %d priority level(s) for %d seconds"),
       
  1413 					  aCount, aPriorities, aDelay);
       
  1414 	test.Next(name);
       
  1415 
       
  1416 	TTime startTime;
       
  1417 	startTime.UniversalTime();
       
  1418 
       
  1419 	// start subprocesses and let them initialise
       
  1420 	RArray<RTestSession> processes;
       
  1421 	TInt threadsAtEachPriority = aCount / aPriorities;
       
  1422 	for (TInt i = 0 ; i < aCount ; ++i)
       
  1423 		{
       
  1424 		RTestSession sess;
       
  1425 		StartOtherProcess(i + 3, sess);
       
  1426 		test_noError(processes.Append(sess));
       
  1427 		sess.SetCurrentDrive(CurrentDrive);
       
  1428 		}
       
  1429 	test.Printf(_L("Started subprocesses: "));
       
  1430 	PrintElapsedTime(startTime);
       
  1431 	
       
  1432 	// then start random accesses to paged memory
       
  1433 	for (TInt i = 0 ; i < aCount ; ++i)
       
  1434 		{
       
  1435 		TThreadPriority pri;
       
  1436 		switch (i / threadsAtEachPriority)
       
  1437 			{
       
  1438 			case 0:  pri = EPriorityLess; break;
       
  1439 			default: pri = EPriorityMuchLess; break;
       
  1440 			}
       
  1441 		processes[i].StartRandomAccessThread(pri);
       
  1442 		}
       
  1443 	test.Printf(_L("Started threads: "));
       
  1444 	PrintElapsedTime(startTime);
       
  1445 
       
  1446 	test_noError(PagingInfo::ResetAll(LocalDriveNumber,EMediaPagingStatsCode));
       
  1447 	User::After(aDelay * 1000000);
       
  1448 	test_noError(PagingInfo::PrintAll(LocalDriveNumber,EMediaPagingStatsCode));
       
  1449 
       
  1450 	test.Printf(_L("Killing subprocesses: "));
       
  1451 	PrintElapsedTime(startTime);
       
  1452 		
       
  1453 	for (TInt i = 0 ; i < aCount ; ++i)
       
  1454 		{
       
  1455 		processes[i].Exec(KillRandomAccessThread);
       
  1456 		processes[i].Kill();
       
  1457 		processes[i].Close();
       
  1458 		}
       
  1459 
       
  1460 	test.Printf(_L("Test finished: "));
       
  1461 	PrintElapsedTime(startTime);
       
  1462 
       
  1463 	processes.Close();
       
  1464 	}
       
  1465 
       
  1466 void TestCacheSize()
       
  1467 	{
       
  1468 	test.Next(_L("Test cache size within bounds"));
       
  1469 	TUint sizeMin = 0;
       
  1470 	TUint sizeMax = 0;
       
  1471 	TUint currentSize = 0;
       
  1472 	DPTest::CacheSize(sizeMin,sizeMax,currentSize);
       
  1473 	test.Printf(_L("  minimum size == %d pages\n"), sizeMin >> 12);
       
  1474 	test.Printf(_L("  maximum size == %d pages\n"), sizeMax >> 12);
       
  1475 	test.Printf(_L("  current size == %d pages\n"), currentSize >> 12);
       
  1476 	test(currentSize >= sizeMin);
       
  1477 	test(currentSize <= sizeMax);
       
  1478 	}
       
  1479 
       
  1480 void RunUnalignedAliasAccessTest()
       
  1481 	{
       
  1482 	test.Next(_L("Test accesses to aliased non-word-aligned data"));
       
  1483 	
       
  1484 	for (TInt size = 0 ; size <= 28 ; ++ size)
       
  1485 		{
       
  1486 		test.Printf(_L("  size = %d:"), size);
       
  1487 		for (TInt align = 0 ; align <= 3 ; ++align)
       
  1488 			{
       
  1489 			test.Printf(_L(" %d"), align);
       
  1490 			TPtrC8 des(LargeDataStart + align, size);
       
  1491 			FlushAllPages();
       
  1492 			OtherProcess.DesRead(des);			
       
  1493 			}
       
  1494 		test.Printf(_L("\n"));
       
  1495 		}
       
  1496 	}
       
  1497 
       
  1498 void TestCodeChunkCreated()
       
  1499 	{
       
  1500 	LoadLibrary();
       
  1501 	TAny* func = (TAny*)PagedLibrary.Lookup(KTestFunctionOrdinal);
       
  1502 	test_notNull(func);
       
  1503 	FlushAllPages();
       
  1504 	test(GetPageState(func) & EPageStateCodeChunkPresent);
       
  1505 	UnloadLibrary();
       
  1506 	FlushAllPages();
       
  1507 	test(!(GetPageState(func) & EPageStateCodeChunkPresent));
       
  1508 	}
       
  1509 
       
  1510 void TestRepeatedLoading()
       
  1511 	{
       
  1512 	test.Next(_L("Test loading/unloading a DLL doesn't leak address space"));
       
  1513 
       
  1514 	for (TInt dll = 1 ; dll <= 7 ; ++dll)
       
  1515 		{
       
  1516 		test.Printf(_L("  trying dll %d...\n"), dll);
       
  1517 		
       
  1518 		RLibrary library;
       
  1519 		test_noError(LoadSpecificLibrary(library, dll, CurrentDrive));
       
  1520 		TLibraryFunction func1 = library.Lookup(1);
       
  1521 		library.Close();
       
  1522 		
       
  1523 		test_noError(LoadSpecificLibrary(library, dll, CurrentDrive));
       
  1524 		TLibraryFunction func2 = library.Lookup(1);
       
  1525 		library.Close();
       
  1526 
       
  1527 		test_equal(func1, func2);
       
  1528 		}
       
  1529 	}
       
  1530 
       
  1531 void RunDriveIndependantTests()
       
  1532 	{
       
  1533 	if (MultipleMemoryModel)
       
  1534 		{
       
  1535 		test.Next(_L("Test code chunk created and destroyed correctly"));
       
  1536 		TestCodeChunkCreated();
       
  1537 		}
       
  1538 	
       
  1539 	SetCurrentDrive('Z');
       
  1540 
       
  1541 	if (CanForcePageOut)
       
  1542 		{
       
  1543 		test.Next(_L("Test accessing pages by executing code"));
       
  1544 		AccessMethod = EAccessExec;
       
  1545 		RunPathTest(*TestPath);
       
  1546 
       
  1547 		test.Next(_L("Test accessing pages by reading code"));
       
  1548 		AccessMethod = EAccessRead;
       
  1549 		RunPathTest(*TestPath);
       
  1550 
       
  1551 		if (!MovingMemoryModel)
       
  1552 			{
       
  1553 			test.Next(_L("Test accessing pages by reading code from another process via an alias"));
       
  1554 			AccessMethod = EAccessAliasRead;
       
  1555 			RunPathTest(*TestPath);
       
  1556 			}
       
  1557 
       
  1558 		test.Next(_L("Test unmapping paged code"));
       
  1559 		AccessMethod = EAccessExec;
       
  1560 		RunUnmapTest(*TestPath);
       
  1561 
       
  1562 		if (!MovingMemoryModel)
       
  1563 			{
       
  1564 			test.Next(_L("Test interactions between two processes"));
       
  1565 			RunMultiProcessTest();
       
  1566 			}
       
  1567 		}
       
  1568 
       
  1569 	RunReadExportDirTest();
       
  1570 	RunPageLockingTest();
       
  1571 	RunWriteToPagedCodeTest();
       
  1572 	RunUnalignedAliasAccessTest();
       
  1573 	TestRepeatedLoading();
       
  1574 	}
       
  1575 
       
  1576 void RunPerDriveTests()
       
  1577 	{
       
  1578 	TestContentsOfPagedDll();
       
  1579 	TestContentsOfPagedDllWithRelocatedData();
       
  1580 	TestKillThreadWhilePaging();
       
  1581 	TestUnloadDllWhilePaging();
       
  1582 	
       
  1583 	TestLargeDll(5);
       
  1584 
       
  1585 	TestManyProcesses(2, 5, 1);
       
  1586 	TestManyProcesses(5, 10, 1);
       
  1587 	TestManyProcesses(10, 20, 1);
       
  1588 	TestManyProcesses(5, 10, 2);
       
  1589 	TestManyProcesses(50, 2, 1);
       
  1590 	}
       
  1591 
       
  1592 void RunAllTests()
       
  1593 	{
       
  1594 
       
  1595 	RunDriveIndependantTests();
       
  1596 	
       
  1597 	for (TInt i = 0 ; i < SupportedDrives.Count() ; ++i)
       
  1598 		{
       
  1599 		SetCurrentDrive(SupportedDrives[i].iDriveLetter);
       
  1600 		OtherProcess.SetCurrentDrive(CurrentDrive);
       
  1601 
       
  1602 		TBuf<32> message;
       
  1603 		message.AppendFormat(_L("Running tests on drive %c:"), (TUint) SupportedDrives[i].iDriveLetter);
       
  1604 		test.Next(message);		
       
  1605 		RunPerDriveTests();
       
  1606 		}
       
  1607 	TestCacheSize();
       
  1608 	}
       
  1609 
       
  1610 // Server implementation ///////////////////////////////////////////////////////
       
  1611 
       
  1612 class CTestSession : public CSession2
       
  1613 	{
       
  1614 public:
       
  1615 	virtual void ServiceL(const RMessage2& aMessage);
       
  1616 	};
       
  1617 
       
  1618 void CTestSession::ServiceL(const RMessage2& aMessage)
       
  1619 	{
       
  1620 	TInt r = KErrNone;
       
  1621 	switch (aMessage.Function())
       
  1622 		{
       
  1623 		case RTestSession::EKill:
       
  1624 			CActiveScheduler::Stop();
       
  1625 			break;
       
  1626 
       
  1627 		case RTestSession::EExec:
       
  1628 			((TFunc)aMessage.Int0())();		   
       
  1629 			break;
       
  1630 
       
  1631 		case RTestSession::ESetCurrentDrive:
       
  1632 			SetCurrentDrive(aMessage.Int0());
       
  1633 			break;
       
  1634 
       
  1635 		case RTestSession::EDesRead:
       
  1636 			{
       
  1637 			TBuf8<32> buf;
       
  1638 			if (buf.MaxSize() < aMessage.GetDesLength(0))
       
  1639 				r = KErrArgument;
       
  1640 			else
       
  1641 				r = aMessage.Read(0, buf);
       
  1642 			}
       
  1643 			break;
       
  1644 
       
  1645 		case RTestSession::ETestPageState:
       
  1646 			TestPageState((TPageState)aMessage.Int0(), (TPhysState)aMessage.Int1());
       
  1647 			break;
       
  1648 			
       
  1649 		case RTestSession::ETestStateTransition:
       
  1650 			TestStateTransition((TPageState)aMessage.Int0());
       
  1651 			break;
       
  1652 
       
  1653 		case RTestSession::EStartRandomAccessThread:
       
  1654 			StartRandomAccessThread((TThreadPriority)aMessage.Int0());
       
  1655 			break;
       
  1656 
       
  1657 		default:
       
  1658 			r = KErrNotSupported;
       
  1659 			break;
       
  1660 		}
       
  1661 	
       
  1662 	aMessage.Complete(r);
       
  1663 	}
       
  1664 
       
  1665 class CTestServer : public CServer2
       
  1666 	{
       
  1667 public:
       
  1668 	CTestServer() : CServer2(0) { }
       
  1669 	virtual CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
       
  1670  };
       
  1671 
       
  1672 CSession2* CTestServer::NewSessionL(const TVersion& /*aVersion*/,const RMessage2& /*aMessage*/) const
       
  1673 	{
       
  1674 	return new (ELeave) CTestSession();
       
  1675 	}
       
  1676 
       
  1677 void DoStartServerL()
       
  1678 	{
       
  1679 	CActiveScheduler* activeScheduler = new CActiveScheduler;
       
  1680 	test_notNull(activeScheduler);
       
  1681 	CActiveScheduler::Install(activeScheduler);
       
  1682 	CTestServer* server = new CTestServer();
       
  1683 	test_notNull(server);
       
  1684 	TBuf<32> name;
       
  1685 	name.AppendFormat(_L("%S-%d"), &KServerName, ProcessNum);
       
  1686 	test_noError(server->Start(name));
       
  1687 	RProcess().Rendezvous(KErrNone);
       
  1688 	CActiveScheduler::Start();
       
  1689 	delete server;
       
  1690 	delete activeScheduler;
       
  1691 	}
       
  1692 
       
  1693 void StartServer()
       
  1694 	{
       
  1695 	CTrapCleanup* cleanupStack = CTrapCleanup::New();
       
  1696 	test_notNull(cleanupStack);
       
  1697 	TRAPD(leaveError,DoStartServerL());	
       
  1698 	test_noError(leaveError);
       
  1699 	delete cleanupStack;
       
  1700 	}
       
  1701 
       
  1702 void SecondaryProcess()
       
  1703 	{
       
  1704 	TBuf<16> cmd;
       
  1705 	User::CommandLine(cmd);
       
  1706 	TLex lex(cmd);
       
  1707 	lex.Val(ProcessNum);
       
  1708 
       
  1709 	TBuf<32> name;
       
  1710 	name.AppendFormat(_L("t_codepaging-%d"), ProcessNum);
       
  1711 	RProcess me;
       
  1712 	test_noError(me.RenameMe(name));
       
  1713 	
       
  1714 	GetSupportedDrives(EFalse);
       
  1715 	Initialise();
       
  1716 	SetCurrentDrive('Z');
       
  1717 	StartServer();
       
  1718 	}
       
  1719 
       
  1720 void MainProcess()
       
  1721 	{
       
  1722 	ProcessNum = 1;
       
  1723 		
       
  1724 	test.Title();
       
  1725 	test.Start(_L("Code paging tests"));
       
  1726 	
       
  1727 	TUint32 memModelAttributes=UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
       
  1728 	TUint32 pagingPolicy = E32Loader::PagingPolicy();
       
  1729 	TBool codePagingSupported = (memModelAttributes & EMemModelAttrCodePaging) != 0;
       
  1730 	TBool pagingPolicyAllowsPaging = pagingPolicy != EKernelConfigCodePagingPolicyNoPaging;
       
  1731 	test_Equal(codePagingSupported, pagingPolicyAllowsPaging);
       
  1732 	if(!codePagingSupported)
       
  1733 		{
       
  1734 		test.Printf(_L("TESTS NOT RUN - Code paging not enabled on system.\n"));
       
  1735 		test.End();
       
  1736 		return;
       
  1737 		}
       
  1738 	
       
  1739 	GetSupportedDrives(ETrue);
       
  1740 	test(SupportedDrives.Count() > 0);
       
  1741 
       
  1742 	// Turn off evil lazy dll unloading
       
  1743 	RLoader l;
       
  1744 	test(l.Connect()==KErrNone);
       
  1745 	test(l.CancelLazyDllUnload()==KErrNone);
       
  1746 	l.Close();
       
  1747 
       
  1748 	CopyDllsToSupportedDrives();
       
  1749 
       
  1750 	Initialise();
       
  1751 
       
  1752 	StartOtherProcess(2, OtherProcess);
       
  1753 
       
  1754 	RunAllTests();
       
  1755 
       
  1756 	OtherProcess.Kill();
       
  1757 	OtherProcess.Close();
       
  1758 	test.End();
       
  1759 	}
       
  1760 
       
  1761 
       
  1762 TInt E32Main()
       
  1763 	{
       
  1764 	if (User::CommandLineLength() == 0)
       
  1765 		MainProcess();
       
  1766 	else
       
  1767 		SecondaryProcess();
       
  1768 	
       
  1769 	return 0;
       
  1770 	}