sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of the License "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // f32test\demandpaging\loader\t_pageldrtst.cpp
sl@0: // Demand Paging Loader Stress Tests
sl@0: // Demand Paging Loader stress tests attempt to cause as much paging as possible
sl@0: // whilst putting the system various types of load.
sl@0: // t_pageldrtst.exe is the root of the tests, it in turn will start copies of 
sl@0: // itself stored in various types of media (t_pageldrtst_rom.exe for example).
sl@0: // It also loads DLLs from various media, each DLL containing simple functions 
sl@0: // that are aligned on page boundaries, so each function call is likely to 
sl@0: // cause a page fault.
sl@0: // Usage:
sl@0: // t_pageldrtst and t_pageldrtst_rom
sl@0: // Common command lines:
sl@0: // t_pageldrtst - run the auto test suite
sl@0: // t_pageldrtst lowmem - run the low memory tests
sl@0: // t_pageldrtst chunks - run the chunk tests
sl@0: // t_pageldrtst chunks+ - run the chunk tests (same as used in autotest)
sl@0: // t_pageldrtst echunks - run the really stressful chunk tests
sl@0: // t_pageldrtst auto debug - run the autotest but with debug output to the serial port
sl@0: // t_pageldrtst d_exc - run the d_exc tests
sl@0: // Arguments:
sl@0: // single - run the tests in a single thread
sl@0: // multiple <numThreads> - run the tests in multiple threads where <numThreads>
sl@0: // auto - dummy param to trick the tests into running the auto test suite with extra params
sl@0: // fullauto - param to make the tests perform the full automatic stress test
sl@0: // interleave - force thread interleaving
sl@0: // prio - each thread reschedules in between each function call, causes lots of context changes
sl@0: // media - perform media access during the tests, very stressful
sl@0: // mmc - only use the mmc media for media access to test file caching
sl@0: // min - min cache size in pages
sl@0: // max - max cache size in pages
sl@0: // chunks - simple chunk stress tests
sl@0: // chunks+ - the chunk auto tests
sl@0: // echunks - extremem chunks tests
sl@0: // nochunkdata - don't check the integrity of the data in the chunks
sl@0: // lowmem - low memory tests
sl@0: // dll - only load dll's
sl@0: // exe - only start exe's (t_pagestress)
sl@0: // self - only start copies of self (t_pageldrtst from various media)
sl@0: // complete - dll, exe and self.
sl@0: // rom - only load from ROM
sl@0: // base - only load the base DLL and exe's (from code)
sl@0: // mixed - rom and base.
sl@0: // all_media - load dlls and exes from all media
sl@0: // debug - switch on debugging information
sl@0: // silent - no output to the screen or serial port
sl@0: // noclean - don't delete copied files on exit
sl@0: // d_exc - run the d_exc tests
sl@0: // global - load dlls once globally
sl@0: // thread - load dlls once per thread
sl@0: // func - load dlls in the test function (default and most stressful)
sl@0: // forward - patern in which to execute function calls 
sl@0: // backward - patern in which to execute function calls 			
sl@0: // random - patern in which to execute function calls 			
sl@0: // all - patern in which to execute function calls (forward, backward and random)
sl@0: // inst - for debugging a parameter passed to a spawned exe to give it an id.
sl@0: // iters <count> - the number of times to loop (a '-' means run forever)
sl@0: // reaper - test the reaper.
sl@0: // btrace - test the btrace code.
sl@0: // defrag - test the ram defrag code.
sl@0: // stressfree - set the page cache to stress free size and run tests.
sl@0: // t_pageldrtst causes a large ammount of paging by repeatedly calling 
sl@0: // functions from multiple DLLs which include 64 functions which have 
sl@0: // been aligned on page boundaries from multiple threads, whilst causing 
sl@0: // background paging by spawning copies of itself and t_pagestress.
sl@0: // The test also endeavours to stress the loader by loading and unloading
sl@0: // DLLs from multiple threads from various types of media at the same 
sl@0: // time as stressing the media, testing chunks, the reaper and changing
sl@0: // thread priorities.
sl@0: // 002 Load thrashing, test rapid loading and unloading of DLLs from 
sl@0: // multiple threads (DEF100158)
sl@0: // 003 Multiple threads loading DLLs in random pattern
sl@0: // 004 Multiple threads loading EXE, SELF and DLLs in random pattern with
sl@0: // all media, loaded in thread with prio change
sl@0: // 005 Multiple threads loading EXE, SELF and DLLs in random pattern with
sl@0: // all media, loaded globally with prio change
sl@0: // 006 Multiple threads loading EXE, SELF and DLLs in random pattern with
sl@0: // all media, loaded in func with process interleaving
sl@0: // 007 Multiple threads loading EXE, SELF and DLLs in random pattern with
sl@0: // all media, loaded in func with process interleaving, prio change
sl@0: // and media access
sl@0: // 008 Low Memory setup test
sl@0: // 009 Low Memory, Multiple threads loading EXE, SELF and DLLs in random 
sl@0: // pattern, loaded in func.
sl@0: // 010 Low Memory setup test
sl@0: // 011 Low Memory, Multiple threads loading EXE, SELF and DLLs in random 
sl@0: // pattern, loaded in func with process interleaving, 
sl@0: // prio change and media access
sl@0: // 012 Close test driver
sl@0: // 013 Chunk tests, Multiple threads loading EXE, SELF and DLLs in random 
sl@0: // pattern with ROM / ROFS media, loaded in func with prio change 
sl@0: // 014 Reaper tests with Multiple threads loading EXE, SELF and DLLs in random 
sl@0: // pattern with all media 
sl@0: // 015 Reaper tests with Multiple threads loading EXE, SELF and DLLs in random 
sl@0: // pattern with all media, prio change and process interleaving
sl@0: // 016 d_exc check test
sl@0: // 
sl@0: //
sl@0: 
sl@0: //! @SYMTestCaseID			KBASE-T_PAGELDRTST-0326
sl@0: //! @SYMTestType			UT
sl@0: //! @SYMPREQ				PREQ1110
sl@0: //! @SYMTestCaseDesc		Demand Paging Loader Stress Tests
sl@0: //! @SYMTestActions			001 Demand Paging loader stress tests...
sl@0: //! @SYMTestExpectedResults All tests should pass.
sl@0: //! @SYMTestPriority        High
sl@0: //! @SYMTestStatus          Implemented
sl@0: 
sl@0: #include <e32test.h>
sl@0: #include <e32rom.h>
sl@0: #include <e32svr.h>
sl@0: #include <u32hal.h>
sl@0: #include <f32file.h>
sl@0: #include <f32dbg.h>
sl@0: #include <e32msgqueue.h>
sl@0: #include <e32math.h>
sl@0: #include <e32btrace.h>
sl@0: #include <d32btrace.h>
sl@0: #include <d32locd.h>
sl@0: #include <hal.h>
sl@0: 
sl@0: #include "t_hash.h"
sl@0: #include "paging_info.h"
sl@0: 
sl@0: #ifndef TEST_AUTOTEST
sl@0: #define TEST_RUN_REAPERTEST
sl@0: #define TEST_RUN_LOWMEMTEST
sl@0: #define TEST_RUN_DEFRAGTEST
sl@0: #define TEST_RUN_D_EXCTEST
sl@0: #define TEST_RUN_CHUNKTEST
sl@0: #define TEST_RUN_AUTOTEST
sl@0: RTest test(_L("T_PAGELDRTST"));
sl@0: #else
sl@0: #ifdef TEST_RUN_REAPERTEST
sl@0: RTest test(_L("T_PAGELDRTST_REAPER"));
sl@0: #endif
sl@0: #ifdef TEST_RUN_LOWMEMTEST
sl@0: RTest test(_L("T_PAGELDRTST_LOWMEM"));
sl@0: #endif
sl@0: #ifdef TEST_RUN_DEFRAGTEST
sl@0: RTest test(_L("T_PAGELDRTST_DEFRAG"));
sl@0: #endif
sl@0: #ifdef TEST_RUN_D_EXCTEST
sl@0: RTest test(_L("T_PAGELDRTST_D_EXC"));
sl@0: #endif
sl@0: #ifdef TEST_RUN_CHUNKTEST
sl@0: RTest test(_L("T_PAGELDRTST_CHUNK"));
sl@0: #endif
sl@0: #ifdef TEST_RUN_AUTOTEST
sl@0: RTest test(_L("T_PAGELDRTST_AUTO"));
sl@0: #endif
sl@0: #endif //TEST_AUTOTEST
sl@0: 
sl@0: const TInt KMessageBufSize = 80;
sl@0: typedef TBuf<KMessageBufSize> TMessageBuf;
sl@0: 
sl@0: //#define TEST_SHORT_TEST
sl@0: //#define TEST_THRASHING_TEST
sl@0: //#define TEST_ADD_FAT_MEDIA
sl@0: #define TEST_DONT_RESET_STATS
sl@0: #define TEST_MINIMAL_STATS
sl@0: //#define TEST_KERN_HEAP
sl@0: #define TEST_ADD_FRAGD_MEDIA
sl@0: #ifdef TEST_ADD_FRAGD_MEDIA
sl@0: #endif
sl@0: 
sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0: //#define WANT_FS_CACHE_STATS 
sl@0: #endif
sl@0: 
sl@0: #ifdef __X86__
sl@0: #define TEST_ON_UNPAGED
sl@0: #define TEST_NO_DEXC_IN_AUTO
sl@0: #endif
sl@0: 
sl@0: 
sl@0: #include "t_pagestress.h"
sl@0: #include "t_pageldrtstdll.h"
sl@0: 
sl@0: #include "t_ramstress.h"
sl@0: 
sl@0: TBool		TestDebug					= EFalse;
sl@0: TBool		TestSilent					= EFalse;
sl@0: TBool		TestExit					= EFalse;
sl@0: #define TEST_EXE			0x01
sl@0: #define TEST_DLL			0x02
sl@0: #define TEST_SELF			0x04
sl@0: #define TEST_EXE_SELF		(TEST_EXE | TEST_SELF)
sl@0: #define TEST_EXE_SELF_DLL	(TEST_EXE | TEST_SELF | TEST_DLL)
sl@0: TInt		TestLoading				    = TEST_EXE_SELF_DLL;
sl@0: 
sl@0: #define TEST_MEDIA_BASE			(1 << KTestMediaBase)
sl@0: #define TEST_MEDIA_ROM			(1 << KTestMediaRom)
sl@0: #define TEST_MEDIA_ROFS			(1 << KTestMediaRofs)
sl@0: #define TEST_MEDIA_EXT			(1 << KTestMediaExt)
sl@0: #define TEST_MEDIA_FAT			(1 << KTestMediaFat)
sl@0: #define TEST_MEDIA_MMC			(1 << KTestMediaMmc)
sl@0: #define TEST_MEDIA_ROM_BASE		(TEST_MEDIA_ROM | TEST_MEDIA_BASE)
sl@0: #define TEST_MEDIA_ALL		(TEST_MEDIA_ROM | TEST_MEDIA_BASE | TEST_MEDIA_ROFS | TEST_MEDIA_EXT | TEST_MEDIA_MMC)
sl@0: 
sl@0: typedef enum
sl@0: {
sl@0: 	KTestMediaBase = 0,
sl@0: 	KTestMediaRom,
sl@0: 	KTestMediaExt,
sl@0: 	KTestMediaRofs,
sl@0: #ifdef TEST_ADD_FAT_MEDIA
sl@0: 	KTestMediaFat,  // this is the last one that is always present.
sl@0: #endif
sl@0: 	KTestMediaMmc,
sl@0: #ifdef TEST_ADD_FRAGD_MEDIA
sl@0: 	KTestMediaNandFrag,
sl@0: 	KTestMediaMmcFrag,
sl@0: #endif
sl@0: 	KTestMediaCOUNT,
sl@0: }ETestMediaType;
sl@0: #ifdef TEST_ADD_FAT_MEDIA
sl@0: #define TEST_MEDIA_COUNT_HACK   (KTestMediaFat + 1)
sl@0: #else
sl@0: #define TEST_MEDIA_COUNT_HACK   (KTestMediaRofs + 1)
sl@0: #endif
sl@0: 
sl@0: typedef enum
sl@0: {
sl@0: 	KTestMediaAccessNone = 0,
sl@0: 	KTestMediaAccessBasic,
sl@0: 	KTestMediaAccessMultipleThreads,
sl@0: 	KTestMediaAccessMultiplePattern,
sl@0: 	KTestMediaAccessMixed,
sl@0: 	KTestMediaAccessCOUNT,
sl@0: }ETestMediaAccess;
sl@0: 
sl@0: TInt		TestWhichMedia			    = TEST_MEDIA_ROM_BASE;
sl@0: TInt		DriveNumber=-1;   // Parameter - Which drive?  -1 = autodetect.
sl@0: TBool		TestSingle					= EFalse;
sl@0: TBool		TestMultiple				= EFalse;
sl@0: TInt		TestMaxLoops				= 20;
sl@0: #define TEST_2MEDIA_THREADS		20
sl@0: #define TEST_ALLMEDIA_THREADS	20
sl@0: TInt		TestMultipleThreadCount		= TEST_2MEDIA_THREADS;
sl@0: TInt		TestInstanceId				= 0;
sl@0: TBool		TestWeAreTheTestBase        = EFalse;
sl@0: TBool		TestBootedFromMmc			= EFalse;
sl@0: TBool		TestOnlyFromMmc				= EFalse;
sl@0: TBool		TestD_Exc					= EFalse;
sl@0: TBool		TestNoClean					= EFalse;
sl@0: TBool		TestFullAutoTest			= EFalse;
sl@0: #define TEST_DLL_GLOBAL		0x01
sl@0: #define TEST_DLL_THREAD		0x02
sl@0: #define TEST_DLL_FUNC		0x04
sl@0: TInt		TestLoadDllHow				= TEST_DLL_FUNC;
sl@0: TBool		TestIsAutomated				= EFalse;
sl@0: 
sl@0: #define TEST_INTERLEAVE_PRIO		EPriorityMore//EPriorityRealTime //23 // KNandThreadPriority - 1
sl@0: TBool		TestInterleave				= EFalse;
sl@0: TFileName	TestNameBuffer;
sl@0: TBool		TestPrioChange				= EFalse;
sl@0: 
sl@0: volatile TBool		TestStopMedia				= EFalse;
sl@0: ETestMediaAccess TestMediaAccess        = KTestMediaAccessNone;
sl@0: #define TEST_NUM_FILES		5
sl@0: 
sl@0: RSemaphore	TestMultiSem;
sl@0: RMsgQueue<TMessageBuf> TestMsgQueue;
sl@0: 
sl@0: #define TEST_LM_NUM_FREE	0
sl@0: #define TEST_LM_BLOCKSIZE	1
sl@0: #define TEST_LM_BLOCKS_FREE	4
sl@0: TBool		TestLowMem					= EFalse;
sl@0: TBool		TestingLowMem				= EFalse;
sl@0: RPageStressTestLdd PagestressLdd;
sl@0: RRamStressTestLdd  RamstressLdd;
sl@0: 
sl@0: TBool		TestBtrace					= EFalse;
sl@0: TBool		TestDefrag					= EFalse;
sl@0: TBool		TestChunks					= EFalse;
sl@0: TBool		TestChunksPlus				= EFalse;
sl@0: TBool		TestExtremeChunks			= EFalse;
sl@0: TBool		TestChunkData				= ETrue;
sl@0: TBool		TestingChunks				= EFalse;
sl@0: volatile TBool		TestDefragTestEnd			= EFalse;
sl@0: TBool		TestingDefrag				= EFalse;
sl@0: volatile TBool		TestThreadsExit				= EFalse;
sl@0: TInt		TestPageSize				= 4096;
sl@0: RChunk		TestChunk;
sl@0: TInt		TestCommitEnd = 0;
sl@0: TUint8*		TestChunkBase = NULL;
sl@0: #define TEST_NUM_PAGES			64
sl@0: #define TEST_NUM_CHUNK_PAGES	(TEST_NUM_PAGES * 2)
sl@0: TBool		TestChunkPageState[TEST_NUM_CHUNK_PAGES];
sl@0: 
sl@0: TBool		TestReaper					= EFalse;
sl@0: TBool		TestingReaper				= EFalse;
sl@0: TBool		TestingReaperCleaningFiles  = EFalse;
sl@0: #define TEST_REAPER_ITERS			20
sl@0: #define TEST_DOT_PERIOD				30
sl@0: TBool		TestStressFree				= EFalse;
sl@0: TInt		TestMinCacheSize = 64 * 4096;
sl@0: TInt		TestMaxCacheSize = 128 * 4096;
sl@0: TBool		TestIsDemandPaged = ETrue;
sl@0: #define TEST_MAX_ZONE_THREADS		8
sl@0: TUint		TestZoneCount = 0;
sl@0: TInt TickPeriod = 15625;
sl@0: 
sl@0: #define TEST_NONE		0x0
sl@0: #define TEST_THRASH		0x1
sl@0: #define TEST_FORWARD	0x2
sl@0: #define TEST_BACKWARD	0x4
sl@0: #define TEST_RANDOM		0x8
sl@0: #define TEST_ALL		(TEST_RANDOM | TEST_BACKWARD | TEST_FORWARD)
sl@0: TUint32	TestWhichTests				= TEST_ALL;
sl@0: _LIT(KRomPath, "z:\\sys\\bin\\");
sl@0: _LIT(KMmcDefaultPath, "d:\\sys\\bin\\");
sl@0: 
sl@0: #define EXISTS(__val) ((__val == KErrNone) ? &KFileExists : &KFileMissing)
sl@0: _LIT(KSysHash,"?:\\Sys\\Hash\\");
sl@0: _LIT(KTestBlank, "");
sl@0: _LIT(KFileExists, "Exists");
sl@0: _LIT(KFileMissing, "Missing");
sl@0: _LIT(KMultipleTest, "Multiple");
sl@0: _LIT(KSingleTest,   "Single  ");
sl@0: _LIT(KTestExe, "Exe ");
sl@0: _LIT(KTestDll, "Dll ");
sl@0: _LIT(KTestSelf, "Self ");
sl@0: _LIT(KTestBase, "Base ");
sl@0: _LIT(KTestRom, "ROM ");
sl@0: _LIT(KTestAll, "All ");
sl@0: _LIT(KTestGlobal, "Global");
sl@0: _LIT(KTestThread, "Thread");
sl@0: _LIT(KTestFunc,  "Func");
sl@0: _LIT(KTestInter, "Interleave ");
sl@0: _LIT(KTestPrio, "Prio ");
sl@0: _LIT(KTestMedia, "Media ");
sl@0: _LIT(KTestLowMem, "LowMem ");
sl@0: _LIT(KTestChunking, "Chunks ");
sl@0: _LIT(KTestEChunking, "EChunks ");
sl@0: _LIT(KTestChunkingPlus, "Chunks+ ");
sl@0: _LIT(KTestReaper, "Reaper ");
sl@0: _LIT(KTestThrash, "Thrash ");
sl@0: _LIT(KTestForward, "Forward ");
sl@0: _LIT(KTestBackward, "Backward ");
sl@0: _LIT(KTestRandom, "Random ");
sl@0: 
sl@0: typedef struct 
sl@0: 	{
sl@0: 	TBool				testFullAutoOnly;
sl@0: 	TInt				testLoading;
sl@0: 	TInt				testWhichMedia;
sl@0: 	TBool				testMultiple;
sl@0: 	TInt				testMaxLoops;
sl@0: 	TInt				testMultipleThreadCount;
sl@0: 	TBool				testLoadDllHow;
sl@0: 	TBool				testInterleave;
sl@0: 	TBool				testPrioChange;
sl@0: 	ETestMediaAccess	testMediaAccess;
sl@0: 	TUint32				testWhichTests;
sl@0: 	TBool				testLowMem;
sl@0: 	TInt				testFreeRam;
sl@0: 	}TTheTests; 
sl@0: 
sl@0: typedef struct
sl@0: 	{
sl@0: 	TInt	ok;
sl@0: 	TInt	fail;
sl@0: 	}TChunkTestPair;
sl@0: 
sl@0: typedef struct
sl@0: 	{
sl@0: 	TChunkTestPair	lock;
sl@0: 	TChunkTestPair	unlock;
sl@0: 	TChunkTestPair	decommit;
sl@0: 	TChunkTestPair	commit;
sl@0: 	TChunkTestPair	check;
sl@0: 	}
sl@0: TChunkTestStats;
sl@0: 
sl@0: TChunkTestStats	TestChunkStats[TEST_NUM_CHUNK_PAGES];
sl@0: 
sl@0: 
sl@0: TPtrC TestPsExeNames[KTestMediaCOUNT] = {	_L("t_pagestress.exe"), 
sl@0: 											_L("t_pagestress_rom.exe"), 
sl@0: 											_L("t_pagestress_ext.exe"), 
sl@0: 											_L("t_pagestress_rofs.exe"), 
sl@0: #ifdef TEST_ADD_FAT_MEDIA
sl@0: 											_L("t_pagestress_fat.exe"),
sl@0: #endif
sl@0: 											_L("t_pagestress_mmc.exe"),
sl@0: #ifdef TEST_ADD_FRAGD_MEDIA
sl@0: 											_L("t_pagestress_nfr.exe"),
sl@0: 											_L("t_pagestress_mfr.exe"),
sl@0: #endif
sl@0: 											};
sl@0: 
sl@0: TPtrC TestPlExeNames[KTestMediaCOUNT] = {	_L("t_pageldrtst.exe"), 
sl@0: 											_L("t_pageldrtst_rom.exe"), 
sl@0: 											_L("t_pageldrtst_ext.exe"), 
sl@0: 											_L("t_pageldrtst_rofs.exe"), 
sl@0: #ifdef TEST_ADD_FAT_MEDIA
sl@0: 											_L("t_pageldrtst_fat.exe"),
sl@0: #endif
sl@0: 											_L("t_pageldrtst_mmc.exe"),
sl@0: #ifdef TEST_ADD_FRAGD_MEDIA
sl@0: 											_L("t_pageldrtst_nfr.exe"),
sl@0: 											_L("t_pageldrtst_mfr.exe"),
sl@0: #endif
sl@0: 											};
sl@0: 
sl@0: _LIT(KDllBaseName,   "t_pageldrtst");
sl@0: 
sl@0: TPtrC TestPlExtNames[KTestMediaCOUNT] = {	_L(".dll"),
sl@0: 											_L("_rom.dll"),
sl@0: 											_L("_ext.dll"),
sl@0: 											_L("_rofs.dll"),
sl@0: #ifdef TEST_ADD_FAT_MEDIA
sl@0: 											_L("_fat.dll"),
sl@0: #endif
sl@0: 											_L("_mmc.dll"),
sl@0: #ifdef TEST_ADD_FRAGD_MEDIA
sl@0: 											_L("_nfr.dll"),
sl@0: 											_L("_mfr.dll"),
sl@0: #endif
sl@0: 											};
sl@0: 
sl@0: 
sl@0: TBool TestDllExesExist[KTestMediaCOUNT] = { EFalse, 
sl@0: 											EFalse,
sl@0: 											EFalse,
sl@0: 											EFalse,
sl@0: #ifdef TEST_ADD_FAT_MEDIA
sl@0: 											EFalse,
sl@0: #endif
sl@0: 											EFalse,
sl@0: #ifdef TEST_ADD_FRAGD_MEDIA
sl@0: 											EFalse,
sl@0: 											EFalse,
sl@0: #endif
sl@0: 											};
sl@0: #define DBGS_PRINT(__args)\
sl@0: 	if (!TestSilent) test.Printf __args;
sl@0: 
sl@0: #define DBGD_PRINT(__args)\
sl@0: 	if (TestDebug) test.Printf __args;
sl@0: 
sl@0: void SendDebugMessage(RMsgQueue<TMessageBuf> *aMsgQueue = NULL, 
sl@0: 					  TMessageBuf            *aBuffer = NULL,
sl@0: 					  RSemaphore	 		 *aTheSem = NULL)
sl@0: 	{
sl@0: 	for (;;)
sl@0: 		{
sl@0: 		aTheSem->Wait();
sl@0: 		TInt r = aMsgQueue->Send(*aBuffer);
sl@0: 		aTheSem->Signal();
sl@0: 		if (r != KErrOverflow)
sl@0: 			return;
sl@0: 		User::After(0);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: #define DEBUG_PRINT(__args)\
sl@0: if (!TestSilent) \
sl@0: 	{\
sl@0: 	if (aMsgQueue && aBuffer && aTheSem)\
sl@0: 		{\
sl@0: 		aBuffer->Zero();\
sl@0: 		aBuffer->Format __args ;\
sl@0: 		SendDebugMessage(aMsgQueue, aBuffer, aTheSem);\
sl@0: 		}\
sl@0: 	else\
sl@0: 		{\
sl@0: 		test.Printf __args ;\
sl@0: 		}\
sl@0: 	}
sl@0: 
sl@0: #define RUNTEST(__test, __error)\
sl@0: 	if (!TestSilent)\
sl@0: 		test(__test == __error);\
sl@0: 	else\
sl@0: 		__test;
sl@0: 
sl@0: #define RUNTEST1(__test)\
sl@0: 	if (!TestSilent)\
sl@0: 		test(__test);
sl@0: 
sl@0: 
sl@0: #define DEBUG_PRINT1(__args)\
sl@0: if (TestDebug)\
sl@0: 	{\
sl@0: 	DEBUG_PRINT(__args)\
sl@0: 	}
sl@0: 
sl@0: #define DOTEST(__operation, __condition)\
sl@0: 	if (aLowMem) \
sl@0: 		{\
sl@0: 		__operation;\
sl@0: 		while (!__condition)\
sl@0: 			{\
sl@0: 			DBGD_PRINT((_L("Releasing some memory on line %d\n"), __LINE__));\
sl@0: 			if (pTheSem)\
sl@0: 				pTheSem->Wait();\
sl@0: 			PagestressLdd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
sl@0: 			if (pTheSem)\
sl@0: 				pTheSem->Signal();\
sl@0: 			__operation;\
sl@0: 			}\
sl@0: 		RUNTEST1(__condition);\
sl@0: 		}\
sl@0: 	else\
sl@0: 		{\
sl@0: 		__operation;\
sl@0: 		RUNTEST1(__condition);\
sl@0: 		}
sl@0: 
sl@0: #define DOTEST1(__var, __func, __ok, __fail)\
sl@0: 	if (aLowMem) \
sl@0: 		{\
sl@0: 		__var = __func;\
sl@0: 		while (__var == __fail)\
sl@0: 			{\
sl@0: 			DBGD_PRINT((_L("Releasing some memory on line %d\n"), __LINE__));\
sl@0: 			if (pTheSem)\
sl@0: 				pTheSem->Wait();\
sl@0: 			PagestressLdd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
sl@0: 			if (pTheSem)\
sl@0: 				pTheSem->Signal();\
sl@0: 			__var = __func;\
sl@0: 			}\
sl@0: 		if (__var != __ok)\
sl@0: 			DBGS_PRINT((_L("Failing on line %d with error %d\n"), __LINE__, __var));\
sl@0: 		RUNTEST1(__var == __ok);\
sl@0: 		}\
sl@0: 	else\
sl@0: 		{\
sl@0: 		__var = __func;\
sl@0: 		RUNTEST1(__var == __ok);\
sl@0: 		}
sl@0: 
sl@0: #define DOLOADALLOC(__numDlls, __pTheLibs, __theSem)\
sl@0: 	if (TestingLowMem)\
sl@0: 		{\
sl@0: 		__pTheLibs = (PageLdrRLibrary *)User::AllocZ(sizeof(PageLdrRLibrary) * __numDlls);\
sl@0: 		while (__pTheLibs == NULL)\
sl@0: 			{\
sl@0: 			DEBUG_PRINT1((_L("Releasing some memory for alloc on line %d\n"), __LINE__));\
sl@0: 			if (__theSem)\
sl@0: 				__theSem->Wait();\
sl@0: 			PagestressLdd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
sl@0: 			if (__theSem)\
sl@0: 				__theSem->Signal();\
sl@0: 			__pTheLibs = (PageLdrRLibrary *)User::AllocZ(sizeof(PageLdrRLibrary) * __numDlls);\
sl@0: 			}\
sl@0: 		}\
sl@0: 	else\
sl@0: 		{\
sl@0: 		__pTheLibs = (PageLdrRLibrary *)User::AllocZ(sizeof(PageLdrRLibrary) * __numDlls);\
sl@0: 		if (__pTheLibs == NULL)\
sl@0: 			return KErrGeneral;\
sl@0: 		}
sl@0: 
sl@0: #define TEST_NEXT(__args) \
sl@0: 	if (!TestSilent)\
sl@0: 		test.Next __args;
sl@0: 
sl@0: void DoStats();
sl@0: void CheckFilePresence(TBool aDoFileCopy);
sl@0: void CleanupFiles(TBool silent);
sl@0: typedef TInt (*TCallFunction)(TUint32 funcIndex, TInt param1, TInt param2);
sl@0: 
sl@0: class PageLdrRLibrary : public RLibrary
sl@0: 	{
sl@0: public:
sl@0: 	TInt TestLoadLibrary(const TDesC& aFileName, TInt aThreadIndex, RMsgQueue<TMessageBuf> *aMsgQueue, TMessageBuf *aBuffer, RSemaphore  *aTheSem);
sl@0: 	TInt CloseLibrary();
sl@0: 	
sl@0: public:	
sl@0: 	TBool				iInUse;
sl@0: 	TUint32				iFuncCount;
sl@0: 	TLibraryFunction	iInitFunc;
sl@0: 	TLibraryFunction	iFunctionCountFunc;
sl@0: 	TCallFunction       iCallFunctionFunc;
sl@0: 	TLibraryFunction	iSetCloseFunc;
sl@0: 	};
sl@0: 
sl@0: TInt PageLdrRLibrary::CloseLibrary()
sl@0: 	{
sl@0: 	if (iInUse)
sl@0: 		{
sl@0: 		if (iSetCloseFunc)
sl@0: 			(iSetCloseFunc)();
sl@0: 		Close();
sl@0: 		iFuncCount = 0;
sl@0: 		iInitFunc = NULL;
sl@0: 		iFunctionCountFunc = NULL;
sl@0: 		iCallFunctionFunc = NULL;
sl@0: 		iSetCloseFunc = NULL;
sl@0: 		iInUse = EFalse;
sl@0: 		}
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: PageLdrRLibrary		theGlobalLibs[PAGELDRTST_MAX_DLLS * KTestMediaCOUNT];
sl@0: 
sl@0: ////////////////////////////////////////////////////////////
sl@0: // Template functions encapsulating ControlIo magic
sl@0: //
sl@0: GLDEF_D template <class C>
sl@0: GLDEF_C TInt controlIo(RFs &fs, TInt drv, TInt fkn, C &c)
sl@0: {
sl@0:     TPtr8 ptrC((TUint8 *)&c, sizeof(C), sizeof(C));
sl@0: 
sl@0:     TInt r = fs.ControlIo(drv, fkn, ptrC);
sl@0: 
sl@0:     return r;
sl@0: }
sl@0: 
sl@0: //
sl@0: // FreeRam
sl@0: //
sl@0: // Get available free ram.
sl@0: //
sl@0: 
sl@0: TInt FreeRam()
sl@0: 	{
sl@0: 	// wait for any async cleanup in the supervisor to finish first...
sl@0: 	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
sl@0: 
sl@0: 	TMemoryInfoV1Buf meminfo;
sl@0: 	TInt r=UserHal::MemoryInfo(meminfo);
sl@0: 	test (r==KErrNone);
sl@0: 	return meminfo().iFreeRamInBytes;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // FindFsNANDDrive
sl@0: //
sl@0: // Find the NAND drive
sl@0: //
sl@0: 
sl@0: static TInt FindFsNANDDrive(RFs& aFs)
sl@0: 	{
sl@0: 	TDriveList driveList;
sl@0: 	TDriveInfo driveInfo;
sl@0: 	TInt r=aFs.DriveList(driveList);
sl@0:     if (r == KErrNone)
sl@0: 		{
sl@0: 		for (TInt drvNum= (DriveNumber<0)?0:DriveNumber; drvNum<KMaxDrives; ++drvNum)
sl@0: 			{
sl@0: 			if(!driveList[drvNum])
sl@0: 				continue;   //-- skip unexisting drive
sl@0: 
sl@0: 			if (aFs.Drive(driveInfo, drvNum) == KErrNone)
sl@0: 				{
sl@0: 				if(driveInfo.iMediaAtt&KMediaAttPageable)
sl@0: 					{
sl@0: 					TBool readOnly = driveInfo.iMediaAtt & KMediaAttWriteProtected;		// skip ROFS partitions
sl@0: 					if(!readOnly && (driveInfo.iType != EMediaHardDisk))
sl@0: 						{
sl@0: 						if ((drvNum==DriveNumber) || (DriveNumber<0))		// only test if running on this drive
sl@0: 							{
sl@0: 							return (drvNum);
sl@0: 							}
sl@0: 						}
sl@0: 					}
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	return (-1);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // FindMMCDriveNumber
sl@0: // 
sl@0: // Find the first read write drive.
sl@0: //
sl@0: 
sl@0: TInt FindMMCDriveNumber(RFs& aFs)
sl@0: 	{
sl@0: 	TDriveInfo driveInfo;
sl@0: 	for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum)
sl@0: 		{
sl@0: 		TInt r = aFs.Drive(driveInfo, drvNum);
sl@0: 		if (r >= 0)
sl@0: 			{
sl@0: 			if (driveInfo.iType == EMediaHardDisk)
sl@0: 				return (drvNum);
sl@0: 			}
sl@0: 		}
sl@0: 	return -1;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // PageLdrRLibrary::TestLoadLibrary
sl@0: //
sl@0: // Load a library and initialise information about that library
sl@0: //
sl@0: 
sl@0: TInt PageLdrRLibrary::TestLoadLibrary(const TDesC&           aFileName,
sl@0: 									  TInt					 aThreadIndex,
sl@0: 									  RMsgQueue<TMessageBuf> *aMsgQueue = NULL, 
sl@0: 									  TMessageBuf           *aBuffer = NULL,
sl@0: 									  RSemaphore			*aTheSem = NULL)
sl@0: 	{
sl@0: 	TInt retVal = KErrNone;
sl@0: 	if (TestingLowMem)
sl@0: 		{
sl@0: 		TBool whinged = EFalse;
sl@0: 		TInt initialFreeRam = 0;
sl@0: 		TInt freeRam = 0;
sl@0: 
sl@0: 		while (1)
sl@0: 			{
sl@0: 			initialFreeRam = FreeRam();
sl@0: 			retVal = Load(aFileName);
sl@0: 			freeRam = FreeRam();
sl@0: 			if (retVal == KErrNoMemory)
sl@0: 				{
sl@0: 				if (!whinged && (freeRam > (4 * TestPageSize)))
sl@0: 					{
sl@0: 					whinged = ETrue;
sl@0: 					DEBUG_PRINT1((_L("Load() %d pages %S\n"), (freeRam / TestPageSize), &aFileName));
sl@0: 					if (TestIsDemandPaged)
sl@0: 						{
sl@0: 						SVMCacheInfo  tempPages;
sl@0: 						UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
sl@0: 
sl@0: 						DEBUG_PRINT1((_L("DPC : min %d max %d curr %d\n"), 
sl@0: 									tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize));
sl@0: 						DEBUG_PRINT1((_L("    : maxFree %d freeRam %d\n"),
sl@0: 									tempPages.iMaxFreeSize, FreeRam()));
sl@0: 						}
sl@0: 					}
sl@0: 				DEBUG_PRINT1((_L("Load() releasing some memory for %S (%d)\n"), &aFileName, retVal));
sl@0: 				if (aTheSem)
sl@0: 					aTheSem->Wait();
sl@0: 				PagestressLdd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);
sl@0: 				if (aTheSem)
sl@0: 					aTheSem->Signal();
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				if (whinged)
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("Load() Ok %d pages (%d) %S\n"), ((initialFreeRam - freeRam) / TestPageSize), (freeRam / TestPageSize), &aFileName));
sl@0: 					}
sl@0: 				break;
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		DEBUG_PRINT1((_L("Loading %S (%d)\n"), &aFileName, aThreadIndex));	 
sl@0: 		retVal = Load(aFileName);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			DEBUG_PRINT1((_L("Load failed %S (%d)\n"), &aFileName, aThreadIndex));	 
sl@0: 			if (TestingReaper )
sl@0: 				{
sl@0: 				TInt tempIndex = 0;
sl@0: 				TBool whinged = EFalse;
sl@0: 				while (    (   (retVal == KErrNotFound) 
sl@0: 							|| (retVal == KErrPermissionDenied) 
sl@0: 							|| (retVal == KErrCorrupt) 
sl@0: 							|| (retVal == KErrInUse)) 
sl@0: 						&& (    TestingReaperCleaningFiles
sl@0: 							|| (tempIndex < TEST_REAPER_ITERS)))
sl@0: 					{
sl@0: 					User::After(2000000);
sl@0: 					if (!whinged)
sl@0: 						{
sl@0: 						DEBUG_PRINT((_L("Load() retrying load for %S (%d)\n"), &aFileName, retVal));
sl@0: 						whinged = ETrue;
sl@0: 						}
sl@0: 					retVal = Load(aFileName);
sl@0: 					if (!TestingReaperCleaningFiles)
sl@0: 						{
sl@0: 						tempIndex ++;
sl@0: 						}
sl@0: 					}
sl@0: 				if (retVal != KErrNone)
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("Load() failing for %S (%d) idx %d\n"), &aFileName, retVal, tempIndex));
sl@0: 					}
sl@0: 				}
sl@0: 			else if (TestingDefrag)
sl@0: 				{
sl@0: 				TInt tempIndex = 0;
sl@0: 				TBool whinged = EFalse;
sl@0: 				while ((retVal == KErrGeneral) && (tempIndex < 10))
sl@0: 					{
sl@0: 					User::After(20000);
sl@0: 					if (!whinged)
sl@0: 						{
sl@0: 						DEBUG_PRINT((_L("Load() retrying load for %S (%d)\n"), &aFileName, retVal));
sl@0: 						whinged = ETrue;
sl@0: 						}
sl@0: 					retVal = Load(aFileName);
sl@0: 					tempIndex ++;
sl@0: 					}
sl@0: 				if (retVal != KErrNone)
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("Load() failing for %S (%d) idx %d\n"), &aFileName, retVal, tempIndex));
sl@0: 					}
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	DEBUG_PRINT1((_L("Loaded %S (%d)\n"), &aFileName, aThreadIndex));	 
sl@0: 	if (retVal == KErrNone)
sl@0: 		{
sl@0: 		iInUse = ETrue;
sl@0: 		iInitFunc = Lookup(PAGELDRTST_FUNC_Init);
sl@0: 		iFunctionCountFunc = Lookup(PAGELDRTST_FUNC_FunctionCount);
sl@0: 		iCallFunctionFunc = (TCallFunction)Lookup(PAGELDRTST_FUNC_CallFunction);
sl@0: 		iSetCloseFunc = Lookup(PAGELDRTST_FUNC_SetClose);
sl@0: 		if (   (iInitFunc != NULL)
sl@0: 			&& (iFunctionCountFunc != NULL)
sl@0: 			&& (iCallFunctionFunc != NULL)
sl@0: 			&& (iSetCloseFunc != NULL))
sl@0: 			{
sl@0: 			retVal = (iInitFunc)();
sl@0: 			if (retVal == KErrNone)
sl@0: 				{
sl@0: 				iFuncCount = (iFunctionCountFunc)();
sl@0: 				if (iFuncCount != 0)
sl@0: 					{
sl@0: 					DEBUG_PRINT1((_L("Loaded ok %S (%d)\n"), &aFileName, aThreadIndex));	 
sl@0: 					return KErrNone;	
sl@0: 					}
sl@0: 				retVal = KErrGeneral;
sl@0: 				DEBUG_PRINT((_L("!!! bad count %S (%d)\n"), &aFileName, aThreadIndex));	 
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("!!! init failed %S (%d)\n"), &aFileName, aThreadIndex));	 
sl@0: 				retVal = KErrGeneral;
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DEBUG_PRINT((_L("!!! missing %S (%d)\n"), &aFileName, aThreadIndex));	 
sl@0: 			retVal = KErrGeneral;
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		DEBUG_PRINT((_L("Load() failed %S %d\n"), &aFileName, retVal));
sl@0: #ifdef WANT_FS_CACHE_STATS
sl@0: 		RFs			 fs;
sl@0: 		if (KErrNone != fs.Connect())
sl@0: 			{
sl@0: 			DEBUG_PRINT(_L("TestLoadLibrary : Can't connect to the FS\n"));
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TFileCacheStats stats1;
sl@0: 			TInt drvNum = FindMMCDriveNumber(fs); 
sl@0: 			controlIo(fs,drvNum, KControlIoFileCacheStats, stats1);
sl@0: 		
sl@0: 			DEBUG_PRINT((_L("FSC: drv %d %c free %d used %d locked %d\n"),
sl@0: 						drvNum, 'a' + drvNum,
sl@0: 						stats1.iFreeCount,
sl@0: 						stats1.iUsedCount,
sl@0: 						stats1.iLockedSegmentCount));
sl@0: 			DEBUG_PRINT((_L("   : alloc %d lock %d closed %d\n"),
sl@0: 						stats1.iAllocatedSegmentCount,
sl@0: 						stats1.iFileCount,
sl@0: 						stats1.iFilesOnClosedQueue));
sl@0: 			fs.Close();
sl@0: 			}
sl@0: #endif //WANT_FS_CACHE_STATS 
sl@0: 
sl@0: 		if (TestIsDemandPaged)
sl@0: 			{
sl@0: 			SVMCacheInfo  tempPages;
sl@0: 			UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
sl@0: 
sl@0: 			DEBUG_PRINT((_L("DPC : min %d max %d curr %d\n"), 
sl@0: 						tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize));
sl@0: 			DEBUG_PRINT((_L("    : maxFree %d freeRam %d\n"),
sl@0: 						tempPages.iMaxFreeSize, FreeRam()));
sl@0: 			}
sl@0: 		}
sl@0: 	return retVal;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // GetNumDlls
sl@0: //
sl@0: // Work out how many Dlls we will play with
sl@0: //
sl@0: TInt GetNumDlls()
sl@0: 	{
sl@0: 	TInt maxDllIndex;
sl@0: 
sl@0: 	switch (TestWhichMedia)
sl@0: 		{
sl@0: 		default:
sl@0: 		case TEST_MEDIA_BASE:	
sl@0: 		case TEST_MEDIA_ROM:
sl@0: 			maxDllIndex = PAGELDRTST_MAX_DLLS;
sl@0: 		break;
sl@0: 
sl@0: 		case TEST_MEDIA_ROM_BASE:
sl@0: 			maxDllIndex = PAGELDRTST_MAX_DLLS * 2;
sl@0: 		break;
sl@0: 
sl@0: 		case TEST_MEDIA_ALL:
sl@0: 			maxDllIndex = PAGELDRTST_MAX_DLLS * KTestMediaCOUNT;
sl@0: 		break;
sl@0: 		}
sl@0: 	return maxDllIndex;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // LoadTheLibs
sl@0: //
sl@0: // Open DLLs for use in the tests.
sl@0: //
sl@0: 
sl@0: TInt LoadTheLibs(PageLdrRLibrary       *aTheLibs,
sl@0:                  TInt                   aLibCount,
sl@0: 				 TInt				    aThreadIndex, 
sl@0:                  RMsgQueue<TMessageBuf> *aMsgQueue = NULL, 
sl@0: 				 TMessageBuf           *aBuffer = NULL, 
sl@0: 				 RSemaphore			   *aTheSem = NULL)
sl@0: 	{
sl@0: 	TBuf<128>			nameBuffer;
sl@0: 	TInt				dllIndex = 0;
sl@0: 	TInt				realDllIndex = 0;
sl@0: 	TInt				dllOffset = -1;
sl@0: 	TInt				testWhich;
sl@0: 	RThread				thisThread;
sl@0: 
sl@0: 	memset(aTheLibs, 0, sizeof(*aTheLibs) * aLibCount);
sl@0: 	for (dllIndex = 0; dllIndex < aLibCount; dllIndex ++)
sl@0: 		{
sl@0: 		realDllIndex = (dllIndex + aThreadIndex) % PAGELDRTST_MAX_DLLS;
sl@0: //		realDllIndex = (dllIndex) % PAGELDRTST_MAX_DLLS;
sl@0: 		if (realDllIndex == 0)
sl@0: 			dllOffset ++;
sl@0: 
sl@0: 		if ((TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ALL)
sl@0: 			testWhich = (dllIndex + dllOffset) % KTestMediaCOUNT;
sl@0: 		else if ((TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ROM_BASE)
sl@0: 			testWhich = ((dllIndex + dllOffset) & 1) ? KTestMediaBase : KTestMediaRom;
sl@0: 		else if (TestWhichMedia & TEST_MEDIA_BASE )
sl@0: 			testWhich = KTestMediaBase;
sl@0: 		else
sl@0: 			testWhich = KTestMediaRom;
sl@0: 		
sl@0: 		if (!TestDllExesExist[testWhich])
sl@0: 			testWhich = KTestMediaBase;
sl@0: 
sl@0: 		nameBuffer.Format(_L("%S%d%S"), &KDllBaseName, realDllIndex, &TestPlExtNames[testWhich]);
sl@0: 		
sl@0: 		DEBUG_PRINT1((_L("LoadTheLibs[%02d] - loading %S\n"), aThreadIndex, &nameBuffer));
sl@0: 		TInt theErr = aTheLibs[dllIndex].TestLoadLibrary(nameBuffer, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 		if (theErr != KErrNone)
sl@0: 			{
sl@0: 			DEBUG_PRINT((_L("LoadTheLibs[%02d] - fail %S %d\n"), aThreadIndex, &nameBuffer, theErr));
sl@0: 			return KErrGeneral;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DEBUG_PRINT1((_L("LoadTheLibs[%02d] - loaded %S OK\n"), aThreadIndex, &nameBuffer));
sl@0: 			}
sl@0: 		if (TestThreadsExit)
sl@0: 			{
sl@0: 			DEBUG_PRINT((_L("LoadTheLibs[%02d] - cancelled\n"), aThreadIndex));
sl@0: 			return KErrCancel;
sl@0: 			}
sl@0: 		if (TestPrioChange)
sl@0: 			{
sl@0: 			TThreadPriority originalThreadPriority = thisThread.Priority();
sl@0: 			DEBUG_PRINT1((_L("LoadTheLibs[%02d] before priority change\n"), aThreadIndex));
sl@0: 			thisThread.SetPriority(EPriorityLess);
sl@0: 			User::AfterHighRes(0);
sl@0: 			thisThread.SetPriority(originalThreadPriority);
sl@0: 			DEBUG_PRINT1((_L("LoadTheLibs[%02d] after priority change\n"), aThreadIndex));
sl@0: 			}
sl@0: 		}
sl@0: 	DEBUG_PRINT((_L("LoadTheLibs[%02d] done\n"), aThreadIndex));
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // CloseTheLibs
sl@0: //
sl@0: // Close the DLLs that we have previously opened
sl@0: //
sl@0: 
sl@0: void CloseTheLibs (PageLdrRLibrary       *aTheLibs,
sl@0:                    TInt                   aLibCount)
sl@0: 	{
sl@0: 	TInt				dllIndex = 0;
sl@0: 	
sl@0: 	for (dllIndex = 0; dllIndex < aLibCount; dllIndex ++)
sl@0: 		{
sl@0: 		aTheLibs[dllIndex].CloseLibrary();
sl@0: 		}
sl@0: 	memset(aTheLibs, 0, sizeof(*aTheLibs) * aLibCount);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // RunThreadForward
sl@0: //
sl@0: // Walk through the function pointer array (forwards) calling each function
sl@0: //
sl@0: 
sl@0: TInt RunThreadForward(TInt				     aThreadIndex, 
sl@0: 					  PageLdrRLibrary		*aTheLibs,
sl@0: 					  TInt					 aMaxDllIndex,
sl@0: 					  RMsgQueue<TMessageBuf> *aMsgQueue = NULL, 
sl@0: 					  TMessageBuf			*aBuffer = NULL, 
sl@0: 					  RSemaphore			*aTheSem = NULL)
sl@0: 	{
sl@0: 	TInt				seed = 1;
sl@0: 	TUint32				index = 0;
sl@0: 	RThread				thisThread;
sl@0: 	PageLdrRLibrary    *pTheLibs = NULL;
sl@0: 	TInt				dllIndex = 0;
sl@0: 
sl@0: 	if (TestLoadDllHow == TEST_DLL_FUNC)
sl@0: 		{
sl@0: 		DOLOADALLOC(aMaxDllIndex, pTheLibs, aTheSem);
sl@0: 		if (pTheLibs)
sl@0: 			{
sl@0: 			TInt retVal = LoadTheLibs(pTheLibs, aMaxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 			if (retVal != KErrNone)
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("Forward[%d] - load fail\n"), aThreadIndex));
sl@0: 				CloseTheLibs (pTheLibs, aMaxDllIndex);
sl@0: 				User::Free(pTheLibs);
sl@0: 				return retVal;
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DEBUG_PRINT((_L("Forward[%d] - alloc fail\n"), aThreadIndex));
sl@0: 			return KErrGeneral;
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		pTheLibs = aTheLibs;
sl@0: 		}
sl@0: 	
sl@0: 	for (dllIndex = 0; dllIndex < aMaxDllIndex; dllIndex ++)
sl@0: 		{
sl@0: 		index = 0;
sl@0: 		while (index < pTheLibs[dllIndex].iFuncCount)
sl@0: 			{
sl@0: 			if (TestPrioChange)
sl@0: 				{
sl@0: 				TThreadPriority originalThreadPriority = thisThread.Priority();
sl@0: 				thisThread.SetPriority(EPriorityLess);
sl@0: 				User::AfterHighRes(0);
sl@0: 				thisThread.SetPriority(originalThreadPriority);
sl@0: 				}
sl@0: 			if (pTheLibs[dllIndex].iCallFunctionFunc)
sl@0: 				seed = pTheLibs[dllIndex].iCallFunctionFunc(index, seed, index);
sl@0: 			else
sl@0: 				DEBUG_PRINT((_L("Forward[%d] : dll %d was NULL\n"), aThreadIndex, dllIndex));
sl@0: 			index ++;
sl@0: 			if (TestThreadsExit)
sl@0: 				break;
sl@0: 			}
sl@0: 		if (TestThreadsExit)
sl@0: 			break;
sl@0: 		}
sl@0: 	if (TestLoadDllHow == TEST_DLL_FUNC)
sl@0: 		{
sl@0: 		CloseTheLibs(pTheLibs, aMaxDllIndex);
sl@0: 		User::Free(pTheLibs);
sl@0: 		}
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // RunThreadBackward
sl@0: //
sl@0: // Walk through the function pointer array (backwards) calling each function
sl@0: //
sl@0: 
sl@0: TInt RunThreadBackward(TInt				      aThreadIndex, 
sl@0: 					   PageLdrRLibrary		 *aTheLibs,
sl@0: 					   TInt					  aMaxDllIndex,
sl@0: 					   RMsgQueue<TMessageBuf> *aMsgQueue = NULL, 
sl@0: 					   TMessageBuf			 *aBuffer = NULL,
sl@0: 					   RSemaphore			 *aTheSem = NULL)
sl@0: 	{
sl@0: 	TInt				seed = 1;
sl@0: 	TUint32				index = 0;
sl@0: 	RThread				thisThread;
sl@0: 	PageLdrRLibrary    *pTheLibs = NULL;
sl@0: 	TInt				dllIndex = 0;
sl@0: 
sl@0: 	if (TestLoadDllHow == TEST_DLL_FUNC)
sl@0: 		{
sl@0: 		DOLOADALLOC(aMaxDllIndex, pTheLibs, aTheSem);
sl@0: 		if (pTheLibs)
sl@0: 			{
sl@0: 			TInt retVal = LoadTheLibs(pTheLibs, aMaxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 			if (retVal != KErrNone)
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("Backward[%d] - load fail\n"), aThreadIndex));
sl@0: 				CloseTheLibs (pTheLibs, aMaxDllIndex);
sl@0: 				User::Free(pTheLibs);
sl@0: 				return retVal;
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DEBUG_PRINT((_L("Backward[%d] - alloc fail\n"), aThreadIndex));
sl@0: 			return KErrGeneral;
sl@0: 			}
sl@0: 		}	
sl@0: 	else
sl@0: 		{
sl@0: 		pTheLibs = aTheLibs;
sl@0: 		}
sl@0: 
sl@0: 	for (dllIndex = aMaxDllIndex - 1; dllIndex >= 0; dllIndex --)
sl@0: 		{
sl@0: 		index = pTheLibs[dllIndex].iFuncCount;
sl@0: 		while (index > 0)
sl@0: 			{
sl@0: 			if (TestPrioChange)
sl@0: 				{
sl@0: 				TThreadPriority originalThreadPriority = thisThread.Priority();
sl@0: 				thisThread.SetPriority(EPriorityLess);
sl@0: 				User::AfterHighRes(0);
sl@0: 				thisThread.SetPriority(originalThreadPriority);
sl@0: 				}
sl@0: 			if (pTheLibs[dllIndex].iCallFunctionFunc)
sl@0: 				seed = pTheLibs[dllIndex].iCallFunctionFunc(index, seed, index);
sl@0: 			else
sl@0: 				DEBUG_PRINT((_L("Backward[%d] : dll %d was NULL\n"), aThreadIndex, dllIndex));
sl@0: 			index --;
sl@0: 			if (TestThreadsExit)
sl@0: 				break;
sl@0: 			}
sl@0: 		if (TestThreadsExit)
sl@0: 			break;
sl@0: 		}
sl@0: 	if (TestLoadDllHow == TEST_DLL_FUNC)
sl@0: 		{
sl@0: 		CloseTheLibs(pTheLibs, aMaxDllIndex);
sl@0: 		User::Free(pTheLibs);
sl@0: 		}
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // RunThreadRandom
sl@0: //
sl@0: // Walk through the function pointer array in a random order a number of times calling each function
sl@0: //
sl@0: 
sl@0: TInt RunThreadRandom(TInt				    aThreadIndex, 
sl@0: 					 PageLdrRLibrary	   *aTheLibs,
sl@0: 					 TInt				    aMaxDllIndex,
sl@0: 					 RMsgQueue<TMessageBuf> *aMsgQueue = NULL, 
sl@0: 					 TMessageBuf		   *aBuffer = NULL,
sl@0: 					 RSemaphore			   *aTheSem = NULL)
sl@0: 	{
sl@0: 	TInt				seed = 1;
sl@0: 	TUint				randNum;
sl@0: 	RThread				thisThread;
sl@0: 	PageLdrRLibrary    *pTheLibs = NULL;
sl@0: 	TUint				dllIndex = 0;
sl@0: 	
sl@0: 	if (TestLoadDllHow == TEST_DLL_FUNC)
sl@0: 		{
sl@0: 		DOLOADALLOC(aMaxDllIndex, pTheLibs, aTheSem);
sl@0: 		if (pTheLibs)
sl@0: 			{
sl@0: 			TInt retVal = LoadTheLibs(pTheLibs, aMaxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 			if (retVal != KErrNone)
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("Random[%d] - load fail\n"), aThreadIndex));
sl@0: 				CloseTheLibs (pTheLibs, aMaxDllIndex);
sl@0: 				User::Free(pTheLibs);
sl@0: 				return retVal;
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DEBUG_PRINT((_L("Random[%d] - alloc fail\n"), aThreadIndex));
sl@0: 			return KErrGeneral;
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		pTheLibs = aTheLibs;
sl@0: 		}
sl@0: 
sl@0: 	
sl@0: 	TUint funcCount = (TUint)pTheLibs[0].iFuncCount;
sl@0: 	TInt iterCount = aMaxDllIndex * funcCount;
sl@0: 	
sl@0: 	// reduce the time for auto tests by reducing the number of cycles.
sl@0: 	if (TestIsAutomated)
sl@0: 		iterCount /= 4;
sl@0: 
sl@0: 	while (iterCount > 0)
sl@0: 		{
sl@0: 		if (TestPrioChange)
sl@0: 			{
sl@0: 			TThreadPriority originalThreadPriority = thisThread.Priority();
sl@0: 			thisThread.SetPriority(EPriorityLess);
sl@0: 			User::AfterHighRes(0);
sl@0: 			thisThread.SetPriority(originalThreadPriority);
sl@0: 			}
sl@0: 		
sl@0: 		randNum = (TUint)Math::Random();
sl@0: 		dllIndex = randNum % (TUint)aMaxDllIndex;
sl@0: 
sl@0: 		randNum %= funcCount;
sl@0: 
sl@0: 		if (   (randNum < funcCount)
sl@0: 		    && ((TInt)dllIndex < aMaxDllIndex))
sl@0: 			{
sl@0: 			if (pTheLibs[dllIndex].iCallFunctionFunc)
sl@0: 				{
sl@0: 				seed = pTheLibs[dllIndex].iCallFunctionFunc(randNum, seed, randNum);
sl@0: 				}
sl@0: 			else
sl@0: 				DEBUG_PRINT((_L("Random[%d] : dll %d was NULL\n"), aThreadIndex, dllIndex));
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DEBUG_PRINT((_L("Random[%d] : %d ERROR dllIndex %u rand %u\n"), aThreadIndex, iterCount, dllIndex, randNum));
sl@0: 			}
sl@0: 		
sl@0: 		--iterCount;
sl@0: 		if (TestThreadsExit)
sl@0: 			break;
sl@0: 		}
sl@0: 
sl@0: 	if (TestLoadDllHow == TEST_DLL_FUNC)
sl@0: 		{
sl@0: 		CloseTheLibs(pTheLibs, aMaxDllIndex);
sl@0: 		User::Free(pTheLibs);
sl@0: 		}
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // ThrashThreadLoad
sl@0: //
sl@0: // Load and unload the DLLs rapidly to show up a timing window in the kernel.
sl@0: //
sl@0: 
sl@0: TInt ThrashThreadLoad (TInt				      aThreadIndex, 
sl@0: 					   PageLdrRLibrary		 *aTheLibs,
sl@0: 					   TInt					  aMaxDllIndex,
sl@0: 					   RMsgQueue<TMessageBuf> *aMsgQueue = NULL, 
sl@0: 					   TMessageBuf			 *aBuffer = NULL,
sl@0: 					   RSemaphore			 *aTheSem = NULL)
sl@0: 	{
sl@0: 	if (TestLoadDllHow == TEST_DLL_FUNC)
sl@0: 		{
sl@0: 		PageLdrRLibrary    *pTheLibs = NULL;
sl@0: 		DOLOADALLOC(aMaxDllIndex, pTheLibs, aTheSem);
sl@0: 		if (pTheLibs)
sl@0: 			{
sl@0: 			TInt retVal = LoadTheLibs(pTheLibs, aMaxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 			if (retVal != KErrNone)
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("Thrash[%d] - load fail\n"), aThreadIndex));
sl@0: 				CloseTheLibs (pTheLibs, aMaxDllIndex);
sl@0: 				User::Free(pTheLibs);
sl@0: 				return retVal;
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DEBUG_PRINT((_L("Thrash[%d] - alloc fail\n"), aThreadIndex));
sl@0: 			return KErrGeneral;
sl@0: 			}
sl@0: 
sl@0: 		CloseTheLibs(pTheLibs, aMaxDllIndex);
sl@0: 		User::Free(pTheLibs);
sl@0: 		}
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // PerformTestThread
sl@0: //
sl@0: // This is the function that actually does the work.
sl@0: // It is complicated a little because test.Printf can only be called from the first thread that calls it 
sl@0: // so if we are using multiple threads we need to use a message queue to pass the debug info from the
sl@0: // child threads back to the parent for the parent to then call printf.
sl@0: //
sl@0: //
sl@0: 
sl@0: LOCAL_C TInt PerformTestThread(TInt					  aThreadIndex, 
sl@0: 							   RMsgQueue<TMessageBuf> *aMsgQueue = NULL, 
sl@0: 							   TMessageBuf			 *aBuffer = NULL,
sl@0: 							   RSemaphore			 *aTheSem = NULL)
sl@0: 	{
sl@0: 	TUint start = User::TickCount();
sl@0: 
sl@0: 	TFullName n(RThread().Name());
sl@0: 
sl@0: 	DEBUG_PRINT((_L("%S : thread %d Executing %S\n"), &TestNameBuffer, aThreadIndex, &n));
sl@0: 	
sl@0: 	// now select how we do the test...
sl@0: 	TInt	iterIndex;
sl@0: 
sl@0: 	PageLdrRLibrary    *pTheLibs = theGlobalLibs;
sl@0: 	TInt				maxDllIndex = GetNumDlls();
sl@0: 
sl@0: 	switch (TestLoadDllHow)
sl@0: 		{
sl@0: 		case TEST_DLL_THREAD:
sl@0: 			pTheLibs = NULL;
sl@0: 			DOLOADALLOC(maxDllIndex, pTheLibs, aTheSem);
sl@0: 			if (pTheLibs)
sl@0: 				{
sl@0: 				TInt retVal = LoadTheLibs(pTheLibs, maxDllIndex, aThreadIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 				if (retVal != KErrNone)
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("Perform[%d] - load fail\n"), aThreadIndex));
sl@0: 					CloseTheLibs (pTheLibs, maxDllIndex);
sl@0: 					User::Free(pTheLibs);
sl@0: 					return retVal;
sl@0: 					}
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("Perform[%d] - alloc fail\n"), aThreadIndex));
sl@0: 				return KErrGeneral;
sl@0: 				}
sl@0: 		break;
sl@0: 
sl@0: 		case TEST_DLL_GLOBAL:
sl@0: 			pTheLibs = theGlobalLibs;
sl@0: 		break;
sl@0: 
sl@0: 		case TEST_DLL_FUNC:
sl@0: 		default:
sl@0: 		// do nowt
sl@0: 		break;
sl@0: 		}
sl@0: 
sl@0: 	TInt    retVal = KErrNone;
sl@0: 	if (TEST_ALL == (TestWhichTests & TEST_ALL))
sl@0: 		{
sl@0: 		#define LOCAL_ORDER_INDEX1	6
sl@0: 		#define LOCAL_ORDER_INDEX2	3
sl@0: 		TInt	order[LOCAL_ORDER_INDEX1][LOCAL_ORDER_INDEX2] = {	{TEST_FORWARD, TEST_BACKWARD,TEST_RANDOM},
sl@0: 																	{TEST_FORWARD, TEST_RANDOM,  TEST_BACKWARD},
sl@0: 																	{TEST_BACKWARD,TEST_FORWARD, TEST_RANDOM},
sl@0: 																	{TEST_BACKWARD,TEST_RANDOM,  TEST_FORWARD},
sl@0: 																	{TEST_RANDOM,  TEST_FORWARD, TEST_BACKWARD},
sl@0: 																	{TEST_RANDOM,  TEST_BACKWARD,TEST_FORWARD}};
sl@0: 		TInt	whichOrder = 0;
sl@0: 
sl@0: 		for (iterIndex = 0; ; )
sl@0: 			{
sl@0: 			TInt    selOrder = ((aThreadIndex + 1) * (iterIndex + 1)) % LOCAL_ORDER_INDEX1;
sl@0: 			for (whichOrder = 0; whichOrder < LOCAL_ORDER_INDEX2; whichOrder ++)
sl@0: 				{
sl@0: 				switch (order[selOrder][whichOrder])
sl@0: 					{
sl@0: 						case TEST_FORWARD:
sl@0: 						DEBUG_PRINT((_L("%S : %d Iter %d.%d Forward\n"),
sl@0: 							&TestNameBuffer, aThreadIndex, iterIndex, whichOrder));
sl@0: 						retVal = RunThreadForward(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 						break;
sl@0: 
sl@0: 						case TEST_BACKWARD:
sl@0: 						DEBUG_PRINT((_L("%S : %d Iter %d.%d Backward\n"),
sl@0: 							&TestNameBuffer, aThreadIndex, iterIndex, whichOrder));
sl@0: 						retVal = RunThreadBackward(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 						break;
sl@0: 
sl@0: 						case TEST_RANDOM:
sl@0: 						DEBUG_PRINT((_L("%S : %d Iter %d.%d Random\n"),
sl@0: 							&TestNameBuffer, aThreadIndex, iterIndex, whichOrder));
sl@0: 						retVal = RunThreadRandom(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 						break;
sl@0: 						
sl@0: 						default: // this is really an error.
sl@0: 						break;
sl@0: 					}
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d.%d finished %d\n"),
sl@0: 					&TestNameBuffer, aThreadIndex, iterIndex, whichOrder, retVal));
sl@0: 				if ((retVal == KErrCancel) && iterIndex > 0)
sl@0: 					retVal = KErrNone;
sl@0: 				if ((retVal != KErrNone) || TestThreadsExit)
sl@0: 					break;
sl@0: 				}
sl@0: 			if ((retVal != KErrNone) || TestThreadsExit)
sl@0: 				break;
sl@0: 			if (++iterIndex >= TestMaxLoops)
sl@0: 				break;
sl@0: 			User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		if (TestWhichTests & TEST_FORWARD)
sl@0: 			{
sl@0: 			for (iterIndex = 0; ; )
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d Forward\n"), &TestNameBuffer, aThreadIndex, iterIndex));
sl@0: 				retVal = RunThreadForward(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d finished %d\n"), &TestNameBuffer, aThreadIndex, iterIndex, retVal));
sl@0: 				if ((retVal == KErrCancel) && iterIndex > 0)
sl@0: 					retVal = KErrNone;
sl@0: 				if ((retVal != KErrNone) || TestThreadsExit)
sl@0: 					break;
sl@0: 				if (++iterIndex >= TestMaxLoops)
sl@0: 					break;
sl@0: 				User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
sl@0: 				}
sl@0: 			}
sl@0: 			
sl@0: 		if (TestWhichTests & TEST_BACKWARD)
sl@0: 			{
sl@0: 			for (iterIndex = 0; ; )
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d Backward\n"), &TestNameBuffer, aThreadIndex, iterIndex));
sl@0: 				retVal = RunThreadBackward(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d finished %d\n"), &TestNameBuffer, aThreadIndex, iterIndex, retVal));
sl@0: 				if ((retVal == KErrCancel) && iterIndex > 0)
sl@0: 					retVal = KErrNone;
sl@0: 				if ((retVal != KErrNone) || TestThreadsExit)
sl@0: 					break;
sl@0: 				if (++iterIndex >= TestMaxLoops)
sl@0: 					break;
sl@0: 				User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
sl@0: 				}
sl@0: 			}
sl@0: 
sl@0: 		if (TestWhichTests & TEST_RANDOM)
sl@0: 			{
sl@0: 			for (iterIndex = 0; ; )
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d Random\n"), &TestNameBuffer, aThreadIndex, iterIndex));
sl@0: 				retVal = RunThreadRandom(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d finished %d\n"), &TestNameBuffer, aThreadIndex, iterIndex, retVal));
sl@0: 				if ((retVal == KErrCancel) && iterIndex > 0)
sl@0: 					retVal = KErrNone;
sl@0: 				if ((retVal != KErrNone) || TestThreadsExit)
sl@0: 					break;
sl@0: 				if (++iterIndex >= TestMaxLoops)
sl@0: 					break;
sl@0: 				User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
sl@0: 				}
sl@0: 			}
sl@0: 		
sl@0: 		if (TestWhichTests & TEST_THRASH)
sl@0: 			{
sl@0: 			for (iterIndex = 0; ; )
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d Thrash Load\n"), &TestNameBuffer, aThreadIndex, iterIndex));
sl@0: 				retVal = ThrashThreadLoad(aThreadIndex, pTheLibs, maxDllIndex, aMsgQueue, aBuffer, aTheSem);
sl@0: 				DEBUG_PRINT((_L("%S : %d Iter %d finished %d\n"), &TestNameBuffer, aThreadIndex, iterIndex, retVal));
sl@0: 				if ((retVal == KErrCancel) && iterIndex > 0)
sl@0: 					retVal = KErrNone;
sl@0: 				if ((retVal != KErrNone) || TestThreadsExit)
sl@0: 					break;
sl@0: 				if (++iterIndex >= TestMaxLoops)
sl@0: 					break;
sl@0: 				User::AfterHighRes(TEST_DOT_PERIOD/3*1000000);
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	if (TestLoadDllHow == TEST_DLL_THREAD)
sl@0: 		{
sl@0: 		CloseTheLibs(pTheLibs, maxDllIndex);
sl@0: 		User::Free(pTheLibs);
sl@0: 		}
sl@0: 
sl@0: 	DEBUG_PRINT((_L("%S : thread %d Exit (tick %u)\n"), &TestNameBuffer, aThreadIndex, User::TickCount() - start));
sl@0: 	return retVal;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // MultipleTestThread
sl@0: //
sl@0: // Thread function, one created for each thread in a multiple thread test.
sl@0: //
sl@0: 
sl@0: LOCAL_C TInt MultipleTestThread(TAny* aUseTb)
sl@0: 	{
sl@0: 	TInt			ret;
sl@0: 	TMessageBuf		localBuffer;
sl@0: 
sl@0: 	if (TestInterleave)	
sl@0: 		{
sl@0: 		RThread				thisThread;
sl@0: 		thisThread.SetPriority((TThreadPriority) TEST_INTERLEAVE_PRIO);
sl@0: 		}
sl@0: 
sl@0: 	ret = PerformTestThread((TInt) aUseTb, &TestMsgQueue, &localBuffer, &TestMultiSem);
sl@0: 	if (!TestingChunks)
sl@0: 		{
sl@0: 		if (ret != KErrNone) 
sl@0: 			User::Panic(_L("LOAD"), KErrGeneral);
sl@0: 		}
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // StartExe
sl@0: //
sl@0: // Start an executable.
sl@0: //
sl@0: 
sl@0: TInt StartExe(RProcess& aTheProcesses, TRequestStatus* aPrStatus, TInt aIndex, TBool aLoadSelf, TBool aLowMem, RSemaphore *pTheSem = NULL)
sl@0: 	{
sl@0: 	TBuf<256>		buffer;
sl@0: 	TInt			testWhich = KTestMediaRom;
sl@0: 	//y_LIT(KTestDebug, "debug");
sl@0: 	_LIT(KTestSilent, "silent");
sl@0: 
sl@0: 	if ((TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ALL)
sl@0: 		testWhich = aIndex % KTestMediaCOUNT;
sl@0: 	else if ((TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ROM_BASE)
sl@0: 		testWhich = (aIndex & 1) ? KTestMediaBase : KTestMediaRom;
sl@0: 	else if (TestWhichMedia & TEST_MEDIA_BASE )
sl@0: 		testWhich = KTestMediaBase;
sl@0: 	else
sl@0: 		testWhich = KTestMediaRom;
sl@0: 
sl@0: 	if (!TestDllExesExist[testWhich])
sl@0: 		testWhich = KTestMediaBase;
sl@0: 
sl@0: 	buffer.Zero();
sl@0: 	TInt ret;
sl@0: 	if (aLoadSelf)
sl@0: 		{
sl@0: 		buffer.Format(_L("single random dll %S iters %d inst %d"),
sl@0: 			/* TestDebug ? &KTestDebug : */ &KTestSilent, TestMaxLoops, aIndex);
sl@0: 		if (TestExtremeChunks)
sl@0: 			buffer.Append(_L(" echunks"));
sl@0: 		else if (TestChunksPlus)
sl@0: 			buffer.Append(_L(" chunks prio"));
sl@0: 		if (TestChunkData == EFalse)
sl@0: 			buffer.Append(_L(" nochunkdata"));
sl@0: 		DBGS_PRINT((_L("%S : Starting Process %d %S %S\n"),
sl@0: 			&TestNameBuffer, aIndex, &TestPlExeNames[testWhich], &buffer));
sl@0: 		DOTEST1(ret,aTheProcesses.Create(TestPlExeNames[testWhich],buffer),KErrNone, KErrNoMemory);
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		buffer.Format(_L("single random %S iters %d inst %d"),
sl@0: 			/* TestDebug ? &KTestDebug : */ &KTestSilent, TestMaxLoops, aIndex);
sl@0: 		DBGS_PRINT((_L("%S : Starting Process %d %S %S\n"),
sl@0: 			&TestNameBuffer, aIndex, &TestPsExeNames[testWhich], &buffer));
sl@0: 		DOTEST1(ret,aTheProcesses.Create(TestPsExeNames[testWhich],buffer),KErrNone, KErrNoMemory);
sl@0: 		}
sl@0: 	if (ret == KErrNone)
sl@0: 		{
sl@0: 		if(aPrStatus)
sl@0: 			{
sl@0: 			aTheProcesses.Logon(*aPrStatus);
sl@0: 			RUNTEST1(*aPrStatus == KRequestPending);	
sl@0: 			}
sl@0: 		aTheProcesses.Resume();
sl@0: 		}
sl@0: 	return ret;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // PerformRomAndFileSystemAccessThread
sl@0: // 
sl@0: // Access the rom and dump it out to one of the writeable partitions...
sl@0: // really just to make the media server a little busy during the test.
sl@0: //
sl@0: TInt PerformRomAndFileSystemAccessThread(TInt					aThreadId,
sl@0: 										 RMsgQueue<TMessageBuf> *aMsgQueue, 
sl@0: 										 TMessageBuf		   *aBuffer,
sl@0: 										 RSemaphore			   *aTheSem,
sl@0: 										 TBool					aLowMem)
sl@0: 	{
sl@0: 	RThread		 thisThread;
sl@0: 	TUint		 maxBytes = KMaxTUint;
sl@0: 	TInt		 startTime = User::TickCount();
sl@0: 	RSemaphore	*pTheSem = aTheSem;
sl@0: 	RFs fs;
sl@0: 	RFile file;
sl@0: 
sl@0: 	if (KErrNone != fs.Connect())
sl@0: 		{
sl@0: 		DEBUG_PRINT(_L("PerformRomAndFileSystemAccessThread : Can't connect to the FS\n"));
sl@0: 		return KErrGeneral;
sl@0: 		}
sl@0: 
sl@0: 	// get info about the ROM...
sl@0: 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
sl@0: 	TUint8* start;
sl@0: 	TUint8* end;
sl@0: 	if(romHeader->iPageableRomStart)
sl@0: 		{
sl@0: 		start = (TUint8*)romHeader + romHeader->iPageableRomStart;
sl@0: 		end = start + romHeader->iPageableRomSize;
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		start = (TUint8*)romHeader;
sl@0: 		end = start + romHeader->iUncompressedSize;
sl@0: 		}
sl@0: 	if (end <= start)
sl@0: 		return KErrGeneral;
sl@0: 
sl@0: 	// read all ROM pages in a random order...and write out to file in ROFs
sl@0: 	TInt pageSize = 0;
sl@0: 	UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&pageSize,0);
sl@0: 
sl@0: 	TUint size = end - start - pageSize;
sl@0: 	if(size > maxBytes)
sl@0: 		size = maxBytes;
sl@0: 
sl@0: 	TUint32 random = 1 + aThreadId;
sl@0: 	TPtrC8  sourceData;
sl@0: 	TUint8* theAddr;
sl@0: 	HBufC8* checkData;
sl@0: 
sl@0: 	DOTEST((checkData = HBufC8::New(pageSize + 10)),
sl@0: 	       (checkData != NULL));
sl@0: 	
sl@0: 	if (!checkData)
sl@0: 		{
sl@0: 		DEBUG_PRINT((_L("RomAndFSThread %S : failed to alloc read buffer\n"), &TestNameBuffer));
sl@0: 		}
sl@0: 
sl@0: 	TInt		drvNum = (TestBootedFromMmc || TestOnlyFromMmc) ? FindMMCDriveNumber(fs) : FindFsNANDDrive(fs);
sl@0: 	TBuf<32>	filename;
sl@0: 	
sl@0: 	filename.Format(_L("?:\\Pageldrtst%d.tmp"), aThreadId);
sl@0: 	if (drvNum >= 0)
sl@0: 		{
sl@0: 		DEBUG_PRINT((_L("%S : Filename %S\n"), &TestNameBuffer, &filename));
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		DEBUG_PRINT((_L("RomAndFSThread : error getting drive num\n")));
sl@0: 		drvNum = 3; //make it 'd' by default.
sl@0: 		}
sl@0: 	filename[0] = 'a' + drvNum;
sl@0: 
sl@0: #ifdef WANT_FS_CACHE_STATS 
sl@0: 	TInt allocatedSegmentCount = 0;
sl@0: 	TInt filesOnClosedQueue = 0;
sl@0: #endif
sl@0: 	TInt ret;
sl@0: 	while(1)
sl@0: 		{
sl@0: 		for(TInt i = size / (pageSize); i>0; --i)
sl@0: 			{
sl@0: 			DEBUG_PRINT1((_L("%S : Opening the file\n"), &TestNameBuffer));
sl@0: 			DOTEST((ret = file.Replace(fs, filename, EFileWrite)),
sl@0: 				   (KErrNone == ret));
sl@0: 
sl@0: 			random = random * 69069 + 1;
sl@0: 			theAddr = (TUint8 *)(start + ((TInt64(random) * TInt64(size - pageSize)) >> 32));
sl@0: 			sourceData.Set(theAddr,pageSize);
sl@0: 			DEBUG_PRINT1((_L("%S : Writing the file\n"), &TestNameBuffer));
sl@0: 			ret = file.Write(sourceData);
sl@0: 			if (ret != KErrNone)
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("%S : Write returned error %d\n"), &TestNameBuffer, ret));
sl@0: 				}
sl@0: 			DEBUG_PRINT1((_L("%S : Closing the file\n"), &TestNameBuffer));
sl@0: 			file.Close();
sl@0: 			
sl@0: 			if (checkData)
sl@0: 				{
sl@0: 				TPtr8  theBuf = checkData->Des();
sl@0: 
sl@0: #ifdef WANT_FS_CACHE_STATS 
sl@0: 				// Page cache
sl@0: 				TFileCacheStats stats1;
sl@0: 				TFileCacheStats stats2;
sl@0: 				ret = controlIo(fs,drvNum, KControlIoFileCacheStats, stats1);
sl@0: 				if ((ret != KErrNone) && (ret != KErrNotSupported))
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("%S : KControlIoFileCacheStats 1 failed %d\n"), &TestNameBuffer, ret));
sl@0: 					}
sl@0: 
sl@0: 				if (aThreadId & 1)
sl@0: 					{
sl@0: 					// flush closed files queue
sl@0: 					ret = fs.ControlIo(drvNum, KControlIoFlushClosedFiles);
sl@0: 					if (ret != KErrNone)
sl@0: 						{
sl@0: 						DEBUG_PRINT((_L("%S : KControlIoFlushClosedFiles failed %d\n"), &TestNameBuffer, ret));
sl@0: 						}
sl@0: 					}
sl@0: 				else
sl@0: #endif //WANT_FS_CACHE_STATS 
sl@0: 					{
sl@0: 					// rename file to make sure it has cleared the cache.				
sl@0: 					TBuf<32>	newname;
sl@0: 					newname.Format(_L("d:\\Pageldrtst%d.temp"), aThreadId);
sl@0: 					if (drvNum >= 0)
sl@0: 						{
sl@0: 						newname[0] = 'a' + drvNum;
sl@0: 						}
sl@0: 					fs.Rename(filename, newname);
sl@0: 					filename = newname;
sl@0: 					}
sl@0: #ifdef WANT_FS_CACHE_STATS 
sl@0: 				ret = controlIo(fs,drvNum, KControlIoFileCacheStats, stats2);
sl@0: 				if (ret != KErrNone && ret != KErrNotSupported)
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("%S : KControlIoFileCacheStats2 failed %d\n"), &TestNameBuffer, ret));
sl@0: 					}
sl@0: 
sl@0: 				allocatedSegmentCount = (allocatedSegmentCount > stats1.iAllocatedSegmentCount) ? allocatedSegmentCount : stats1.iAllocatedSegmentCount;
sl@0: 				filesOnClosedQueue = (filesOnClosedQueue > stats1.iFilesOnClosedQueue) ? filesOnClosedQueue : stats1.iFilesOnClosedQueue;
sl@0: #endif //WANT_FS_CACHE_STATS 
sl@0: 
sl@0: 				DOTEST((ret = file.Open(fs, filename, EFileRead)),
sl@0: 					   (KErrNone == ret));
sl@0: 				// now read back the page that we wrote and compare with the source.
sl@0: 				ret = file.Read(0, theBuf, pageSize);
sl@0: 				if (ret == KErrNone)
sl@0: 					{		
sl@0: 					ret = sourceData.Compare(theBuf);
sl@0: 					if (ret != 0)
sl@0: 						{
sl@0: 						DEBUG_PRINT((_L("%S : read compare error %d\n"), &TestNameBuffer, ret));
sl@0: 						}
sl@0: 					}
sl@0: 				else
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("%S : failed read compare, error %d\n"), &TestNameBuffer, ret));
sl@0: 					}
sl@0: 				file.Close();
sl@0: 				}
sl@0: 			DEBUG_PRINT1((_L("%S : Deleting the file\n"), &TestNameBuffer));
sl@0: 			ret = fs.Delete(filename);
sl@0: 			if (KErrNone != ret)
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("%S [%d] Delete %S Failed %d!\n"), &TestNameBuffer, aThreadId, &filename, ret));
sl@0: 				}
sl@0: 		
sl@0: 			if (TestPrioChange)
sl@0: 				{
sl@0: 				TThreadPriority originalThreadPriority = thisThread.Priority();
sl@0: 				DEBUG_PRINT1((_L("%S [%d] media thread before priority change, stop = %d\n"), &TestNameBuffer, aThreadId, TestStopMedia));
sl@0: 				thisThread.SetPriority(EPriorityLess);
sl@0: 				User::AfterHighRes(0);
sl@0: 				thisThread.SetPriority(originalThreadPriority);
sl@0: 				DEBUG_PRINT1((_L("%S [%d] media thread after priority change, stop = %d\n"), &TestNameBuffer, aThreadId, TestStopMedia));
sl@0: 				}
sl@0: 			if (TestStopMedia)
sl@0: 				break;
sl@0: 			}
sl@0: 		if (TestStopMedia)
sl@0: 			break;
sl@0: 		}
sl@0: 
sl@0: #ifdef WANT_FS_CACHE_STATS 
sl@0: 	DEBUG_PRINT((_L("%S : [%d] allocPageCount %d filesClosedQueue %d \n"),&TestNameBuffer, aThreadId,allocatedSegmentCount,filesOnClosedQueue));
sl@0: #endif //WANT_FS_CACHE_STATS 
sl@0: 
sl@0: 	if (checkData)
sl@0: 		{
sl@0: 		delete checkData;
sl@0: 		}
sl@0: 	fs.Close();
sl@0: 	DEBUG_PRINT1((_L("Done in %d ticks\n"), User::TickCount() - startTime));
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // PerformFileSystemAccessThread
sl@0: // 
sl@0: // Access the rom and dump it out to one of the writeable partitions...
sl@0: // really just to make the media server a little busy during the test.
sl@0: //
sl@0: TInt PerformFileSystemAccessThread(TInt					    aThreadId,
sl@0: 								   RMsgQueue<TMessageBuf>   *aMsgQueue, 
sl@0: 								   TMessageBuf	           *aBuffer,
sl@0: 								   RSemaphore			   *aTheSem,
sl@0: 								   TBool					aLowMem)
sl@0: 	{
sl@0: 	RThread		 thisThread;
sl@0: 	TInt		 startTime = User::TickCount();
sl@0: 	RSemaphore	*pTheSem = aTheSem;
sl@0: 	RFs			 fs;
sl@0: 	RFile		 file;
sl@0: 	if (KErrNone != fs.Connect())
sl@0: 		{
sl@0: 		DEBUG_PRINT(_L("PerformFileSystemAccessThread : Can't connect to the FS\n"));
sl@0: 		return KErrGeneral;
sl@0: 		}
sl@0: 
sl@0: 	// read all ROM pages in a random order...and write out to file in ROFs
sl@0: 	TInt pageSize = 0;
sl@0: 	UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&pageSize,0);
sl@0: 
sl@0: 	HBufC8* checkData;
sl@0: 	HBufC8* sourceData;
sl@0: 	TUint32 random = 1 + aThreadId;
sl@0: 	TInt	dataSize = pageSize + (pageSize / 2);
sl@0: 	
sl@0: 	DOTEST((sourceData = HBufC8::New(dataSize)),
sl@0: 	       (sourceData != NULL));
sl@0: 	if (!sourceData)
sl@0: 		{
sl@0: 		DEBUG_PRINT((_L("RomAndFSThread %S : failed to alloc read buffer\n"), &TestNameBuffer));
sl@0: 		fs.Close();
sl@0: 		return KErrGeneral;
sl@0: 		}
sl@0: 
sl@0: 	DOTEST((checkData = HBufC8::New(dataSize)),
sl@0: 	       (checkData != NULL));
sl@0: 	if (!checkData)
sl@0: 		{
sl@0: 		DEBUG_PRINT((_L("RomAndFSThread %S : failed to alloc read buffer\n"), &TestNameBuffer));
sl@0: 		}
sl@0: 
sl@0: 	TInt		drvNum = (TestBootedFromMmc || TestOnlyFromMmc) ? FindMMCDriveNumber(fs) : FindFsNANDDrive(fs);
sl@0: 	TBuf<32>	filename;
sl@0: 	
sl@0: 	if (drvNum < 0)
sl@0: 		{
sl@0: 		drvNum = 3; //make it 'd' by default.
sl@0: 		DEBUG_PRINT((_L("FSAccessThread : error getting drive num\n")));
sl@0: 		}
sl@0: 
sl@0: #ifdef WANT_FS_CACHE_STATS 
sl@0: 	TInt allocatedSegmentCount = 0;
sl@0: 	TInt filesOnClosedQueue = 0;
sl@0: #endif
sl@0: 	TInt fileIndex;
sl@0: 	TInt ret;
sl@0: 
sl@0: 	TPtr8  pBuf = sourceData->Des();
sl@0: 	
sl@0: 	while (1)
sl@0: 		{
sl@0: 		TUint32 randomStart = random;
sl@0: 		// write the file
sl@0: 		for (fileIndex = 0; fileIndex < TEST_NUM_FILES; fileIndex ++)
sl@0: 			{
sl@0: 			filename.Format(_L("%c:\\pldrtst%d_%d.tmp"), 'a' + drvNum, aThreadId, fileIndex);
sl@0: 
sl@0: 			DEBUG_PRINT1((_L("%S : Opening the file\n"), &TestNameBuffer));
sl@0: 
sl@0: 			DOTEST ((ret = file.Replace(fs, filename, EFileWrite)),
sl@0: 				   (KErrNone == ret));
sl@0: 
sl@0: 			pBuf.Zero();			
sl@0: 			if (fileIndex & 1)
sl@0: 				{
sl@0: 				TInt fillSize = dataSize / sizeof(TUint32);
sl@0: 				while (fillSize > 0)
sl@0: 					{
sl@0: 					random = random * 69069 + 1;
sl@0: 					pBuf.Append((const TUint8 *) &random, sizeof(random));
sl@0: 					fillSize --;
sl@0: 					}
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				pBuf.Fill('x',dataSize);
sl@0: 				}
sl@0: 		
sl@0: 
sl@0: 			DEBUG_PRINT1((_L("%S : Writing the file\n"), &TestNameBuffer));
sl@0: 			ret = file.Write(sourceData->Des());
sl@0: 			if (ret != KErrNone)
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("%S : Write returned error %d\n"), &TestNameBuffer, ret));
sl@0: 				}
sl@0: 			DEBUG_PRINT1((_L("%S : Closing the file\n"), &TestNameBuffer));
sl@0: 			file.Close();
sl@0: 			}
sl@0: 
sl@0: 		random = randomStart;
sl@0: 		// check the file
sl@0: 		for (fileIndex = 0; fileIndex < TEST_NUM_FILES; fileIndex ++)
sl@0: 			{
sl@0: 			filename.Format(_L("%c:\\pldrtst%d_%d.tmp"), 'a' + drvNum, aThreadId, fileIndex);
sl@0: 			
sl@0: 			if (checkData)
sl@0: 				{
sl@0: 				TPtr8  theBuf = checkData->Des();
sl@0: 
sl@0: #ifdef WANT_FS_CACHE_STATS 
sl@0: 				// Page cache
sl@0: 				TFileCacheStats stats1;
sl@0: 				TFileCacheStats stats2;
sl@0: 				ret = controlIo(fs,drvNum, KControlIoFileCacheStats, stats1);
sl@0: 				if ((ret != KErrNone) && (ret != KErrNotSupported))
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("%S : KControlIoFileCacheStats 1 failed %d\n"), &TestNameBuffer, ret));
sl@0: 					}
sl@0: 
sl@0: 				if (aThreadId & 1)
sl@0: 					{
sl@0: 					// flush closed files queue
sl@0: 					ret = fs.ControlIo(drvNum, KControlIoFlushClosedFiles);
sl@0: 					if (ret != KErrNone)
sl@0: 						{
sl@0: 						DEBUG_PRINT((_L("%S : KControlIoFlushClosedFiles failed %d\n"), &TestNameBuffer, ret));
sl@0: 						}
sl@0: 					}
sl@0: 				else
sl@0: #endif //WANT_FS_CACHE_STATS 
sl@0: 					{
sl@0: 					// rename file to make sure it has cleared the cache.				
sl@0: 					TBuf<32>	newname;
sl@0: 					newname.Format(_L("%c:\\pldrtst%d_%d.temp"), 'a' + drvNum, aThreadId, fileIndex);
sl@0: 					fs.Rename(filename, newname);
sl@0: 					filename = newname;
sl@0: 					}
sl@0: #ifdef WANT_FS_CACHE_STATS 
sl@0: 				ret = controlIo(fs,drvNum, KControlIoFileCacheStats, stats2);
sl@0: 				if (ret != KErrNone && ret != KErrNotSupported)
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("%S : KControlIoFileCacheStats2 failed %d\n"), &TestNameBuffer, ret));
sl@0: 					}
sl@0: 				allocatedSegmentCount = (allocatedSegmentCount > stats1.iAllocatedSegmentCount) ? allocatedSegmentCount : stats1.iAllocatedSegmentCount;
sl@0: 				filesOnClosedQueue = (filesOnClosedQueue > stats1.iFilesOnClosedQueue) ? filesOnClosedQueue : stats1.iFilesOnClosedQueue;
sl@0: #endif //WANT_FS_CACHE_STATS 
sl@0: 
sl@0: 				DOTEST((ret = file.Open(fs, filename, EFileRead)),
sl@0: 					   (KErrNone == ret));
sl@0: 				// now read back the page that we wrote and compare with the source.
sl@0: 				ret = file.Read(0, theBuf, dataSize);
sl@0: 				if (ret == KErrNone)
sl@0: 					{
sl@0: 					pBuf.Zero();			
sl@0: 					if (fileIndex & 1)
sl@0: 						{
sl@0: 						TInt fillSize = dataSize / sizeof(TUint32);
sl@0: 						while (fillSize > 0)
sl@0: 							{
sl@0: 							random = random * 69069 + 1;
sl@0: 							pBuf.Append((const TUint8 *) &random, sizeof(random));
sl@0: 							fillSize --;
sl@0: 							}
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						pBuf.Fill('x',dataSize);
sl@0: 						}
sl@0: 
sl@0: 					ret = sourceData->Des().Compare(theBuf);
sl@0: 					if (ret != 0)
sl@0: 						{
sl@0: 						DEBUG_PRINT((_L("%S :compare error %S %d\n"), &TestNameBuffer, &filename, ret));
sl@0: 						}
sl@0: 					}
sl@0: 				else
sl@0: 					{
sl@0: 					DEBUG_PRINT((_L("%S : failed read compare, error %d\n"), &TestNameBuffer, ret));
sl@0: 					}
sl@0: 				file.Close();
sl@0: 				}
sl@0: 			DEBUG_PRINT1((_L("%S : Deleting the file\n"), &TestNameBuffer));
sl@0: 			ret = fs.Delete(filename);
sl@0: 			if (KErrNone != ret)
sl@0: 				{
sl@0: 				DEBUG_PRINT((_L("%S [%d] Delete %S Failed %d!\n"), &TestNameBuffer, aThreadId, &filename, ret));
sl@0: 				}
sl@0: 			if (TestPrioChange)
sl@0: 				{
sl@0: 				TThreadPriority originalThreadPriority = thisThread.Priority();
sl@0: 				thisThread.SetPriority(EPriorityLess);
sl@0: 				User::AfterHighRes(0);
sl@0: 				thisThread.SetPriority(originalThreadPriority);
sl@0: 				}
sl@0: 			if (TestStopMedia)
sl@0: 				break;
sl@0: 			}
sl@0: 		if (TestStopMedia)
sl@0: 			break;
sl@0: 		}
sl@0: #ifdef WANT_FS_CACHE_STATS 
sl@0: 	DEBUG_PRINT((_L("%S : [%d] allocPageCount %d filesClosedQueue %d \n"),&TestNameBuffer, aThreadId,allocatedSegmentCount,filesOnClosedQueue));
sl@0: #endif //WANT_FS_CACHE_STATS 
sl@0: 
sl@0: 	if (checkData)
sl@0: 		{
sl@0: 		delete checkData;
sl@0: 		}
sl@0: 	delete sourceData;
sl@0: 	fs.Close();
sl@0: 	DEBUG_PRINT1((_L("Done in %d ticks\n"), User::TickCount() - startTime));
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // PerformRomAndFileSystemAccess
sl@0: //
sl@0: // Thread function, kicks off the file system access.
sl@0: //
sl@0: 
sl@0: LOCAL_C TInt PerformRomAndFileSystemAccess(TAny* aParam)
sl@0: 	{
sl@0: 	TMessageBuf			localBuffer;
sl@0: 	TInt				threadId = (TInt) aParam;
sl@0: 	TInt				retVal = KErrGeneral;
sl@0: 
sl@0: 	if (TestInterleave)	
sl@0: 		{
sl@0: 		RThread				thisThread;
sl@0: 		thisThread.SetPriority((TThreadPriority) TEST_INTERLEAVE_PRIO);
sl@0: 		}
sl@0: 
sl@0: 	switch (TestMediaAccess)
sl@0: 		{
sl@0: 		default:
sl@0: 		break;
sl@0: 		
sl@0: 		case KTestMediaAccessBasic:
sl@0: 		case KTestMediaAccessMultipleThreads:
sl@0: 			retVal = PerformRomAndFileSystemAccessThread(threadId, &TestMsgQueue, &localBuffer, &TestMultiSem, TestingLowMem);	
sl@0: 		break;
sl@0: 				
sl@0: 		case KTestMediaAccessMultiplePattern:
sl@0: 			retVal = PerformFileSystemAccessThread(threadId, &TestMsgQueue, &localBuffer, &TestMultiSem, TestingLowMem);
sl@0: 		break;
sl@0: 
sl@0: 		case KTestMediaAccessMixed:
sl@0: 			if (threadId < ((TestMultipleThreadCount + 1) / 2))
sl@0: 				retVal = PerformRomAndFileSystemAccessThread(threadId, &TestMsgQueue, &localBuffer, &TestMultiSem, TestingLowMem);	
sl@0: 			else
sl@0: 				retVal = PerformFileSystemAccessThread(threadId, &TestMsgQueue, &localBuffer, &TestMultiSem, TestingLowMem);
sl@0: 		break;
sl@0: 		}
sl@0: 	return retVal;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // DisplayTestBanner
sl@0: // 
sl@0: // Output a header showing the test parameters.
sl@0: //
sl@0: 
sl@0: void DisplayTestBanner(TBool aMultiple)
sl@0: 	{
sl@0: 	DBGS_PRINT((_L("%S : what = %S%S%S(0x%x), media = %S%S%S(0x%x)\n"),
sl@0: 				aMultiple ? &KMultipleTest : &KSingleTest,
sl@0: 				TestLoading & TEST_EXE ? &KTestExe : &KTestBlank,
sl@0:  				TestLoading & TEST_DLL ? &KTestDll : &KTestBlank,
sl@0:  				TestLoading & TEST_SELF ? &KTestSelf : &KTestBlank,
sl@0: 				TestLoading,
sl@0: 				TestWhichMedia & TEST_MEDIA_BASE ? &KTestBase : &KTestBlank,
sl@0: 				TestWhichMedia & TEST_MEDIA_ROM ? &KTestRom : &KTestBlank,
sl@0: 				(TestWhichMedia & TEST_MEDIA_ALL) == TEST_MEDIA_ALL ? &KTestAll : &KTestBlank,
sl@0: 				TestWhichMedia));
sl@0: 	DBGS_PRINT((_L("         : maxLoops = %d, threads = %d, loadHow = %S (0x%x)\n"),
sl@0: 				TestMaxLoops,
sl@0: 				TestMultipleThreadCount,
sl@0: 				TestLoadDllHow == TEST_DLL_GLOBAL ? &KTestGlobal : TestLoadDllHow == TEST_DLL_THREAD ? &KTestThread : &KTestFunc, TestLoadDllHow));
sl@0: 	DBGS_PRINT((_L("         : options = %S%S%S%S%S%S, which = %S%S%S%S (0x%x)\n"),
sl@0: 				TestInterleave ? &KTestInter : &KTestBlank,
sl@0: 				TestPrioChange ? &KTestPrio: &KTestBlank,
sl@0: 				(TestMediaAccess == KTestMediaAccessNone) ? &KTestBlank : &KTestMedia,
sl@0: 				TestingLowMem ? &KTestLowMem : &KTestBlank, 
sl@0: 				TestExtremeChunks ? &KTestEChunking : TestChunksPlus ? &KTestChunkingPlus : TestingChunks ? &KTestChunking : &KTestBlank, 
sl@0: 				TestingReaper ? &KTestReaper : &KTestBlank, 
sl@0: 				TestWhichTests & TEST_THRASH ? &KTestThrash : &KTestBlank,
sl@0: 				TestWhichTests & TEST_FORWARD ? &KTestForward : &KTestBlank,
sl@0: 				TestWhichTests & TEST_BACKWARD ? &KTestBackward : &KTestBlank,
sl@0: 				TestWhichTests & TEST_RANDOM ? &KTestRandom : &KTestBlank,
sl@0: 				TestWhichTests));
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoSingleTest
sl@0: // 
sl@0: // Perform the single thread test, spawning a number of threads.
sl@0: //
sl@0: 
sl@0: LOCAL_C TInt DoSingleTest(TBool aLowMem = EFalse)
sl@0: 	{
sl@0: 	TUint        start = User::TickCount();
sl@0: 	RSemaphore	*pTheSem = NULL;
sl@0: 	TInt ret = KErrNone;
sl@0: 	DisplayTestBanner(EFalse);
sl@0: 
sl@0: 	if (aLowMem)
sl@0: 		{
sl@0: 		DOTEST1(ret,TestMultiSem.CreateLocal(1),KErrNone, KErrNoMemory);
sl@0: 		pTheSem = &TestMultiSem;
sl@0: 		}
sl@0: 	if (TestLoading & TEST_EXE)
sl@0: 		{
sl@0: 		RProcess		theProcess;
sl@0: 		TRequestStatus	status;
sl@0: 		
sl@0: 		if (StartExe(theProcess, &status, 0, EFalse, aLowMem, pTheSem) == KErrNone)
sl@0: 			{
sl@0: 			User::WaitForRequest(status);
sl@0: 			if (theProcess.ExitType() == EExitPanic)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("%S : Process Panic'd...\n"), &TestNameBuffer));	
sl@0: 				}
sl@0: 			theProcess.Close();
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	if (TestLoading & TEST_SELF)
sl@0: 		{
sl@0: 		RProcess		theProcess;
sl@0: 		TRequestStatus	status;
sl@0: 		
sl@0: 		if (StartExe(theProcess, &status, 0, ETrue, aLowMem,pTheSem) == KErrNone)
sl@0: 			{
sl@0: 			User::WaitForRequest(status);
sl@0: 			if (theProcess.ExitType() == EExitPanic)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("%S : Process Panic'd...\n"), &TestNameBuffer));
sl@0: 				}
sl@0: 			theProcess.Close();
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	if (TestLoading	& TEST_DLL)
sl@0: 		{
sl@0: 		TInt maxDlls = GetNumDlls();
sl@0: 		if (TestLoadDllHow == TEST_DLL_GLOBAL)
sl@0: 			{
sl@0: 			TInt retVal = LoadTheLibs(theGlobalLibs, maxDlls, TestInstanceId, NULL, NULL, pTheSem);
sl@0: 			if (retVal != KErrNone)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("DoSingleTest - unable to load libs\n") ));
sl@0: 				CloseTheLibs (theGlobalLibs, PAGELDRTST_MAX_DLLS);
sl@0: 				if (aLowMem)
sl@0: 					{
sl@0: 					TestMultiSem.Close();
sl@0: 					}
sl@0: 				return KErrGeneral;
sl@0: 				}
sl@0: 			}
sl@0: 
sl@0: 		ret = PerformTestThread((TInt) TestInstanceId, NULL, NULL, pTheSem);
sl@0: 
sl@0: 		if (TestLoadDllHow == TEST_DLL_GLOBAL)
sl@0: 			{
sl@0: 			CloseTheLibs(theGlobalLibs, maxDlls);
sl@0: 			}
sl@0: 		}
sl@0: 	if (aLowMem)
sl@0: 		{
sl@0: 		TestMultiSem.Close();
sl@0: 		}
sl@0: 
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		TInt end = User::TickCount();
sl@0: 		TInt time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 		DBGS_PRINT((_L("\n%S : Single Test : (%u seconds)\n"), &TestNameBuffer, time));
sl@0: 		}
sl@0: 
sl@0: 	return ret;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // FillPage
sl@0: //
sl@0: // Fill a page with test data
sl@0: //
sl@0: 
sl@0: void FillPage(TUint aOffset)
sl@0: 	{
sl@0: 	if (TestChunkData)
sl@0: 		{
sl@0: 		TUint32* ptr = (TUint32 *)((TUint8 *)TestChunkBase+aOffset);
sl@0: 		TUint32* ptrEnd = (TUint32 *)((TUint8 *)ptr + TestPageSize);
sl@0: 		do 
sl@0: 			{
sl@0: 			*ptr = 0x55000000 + aOffset;
sl@0: 			ptr ++;
sl@0: 			aOffset += 4;
sl@0: 			}
sl@0: 		while(ptr<ptrEnd);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // CheckPage
sl@0: //
sl@0: // Check a page matches test data....
sl@0: //
sl@0: 
sl@0: TBool CheckPage(TUint index, TUint aOffset)
sl@0: 	{
sl@0: 	TBool ret = ETrue;
sl@0: 	if (TestChunkData)
sl@0: 		{
sl@0: 		TUint32* ptr = (TUint32 *)((TUint8 *)TestChunkBase+aOffset);
sl@0: 		TUint32* ptrEnd = (TUint32 *)((TUint8 *)ptr + TestPageSize);
sl@0: 		do
sl@0: 			{
sl@0: 			if (*ptr != (0x55000000 + aOffset)) 
sl@0: 				break;
sl@0: 			ptr ++;
sl@0: 			aOffset += 4;
sl@0: 			}
sl@0: 		while(ptr<ptrEnd);
sl@0: 		if (ptr==ptrEnd)
sl@0: 			{
sl@0: 			TestChunkStats[index].check.ok ++;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TestChunkStats[index].check.fail ++;
sl@0: 			ret = EFalse;
sl@0: 			}
sl@0: 		}
sl@0: 	return ret;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoSomeChunking
sl@0: //
sl@0: // Lock and unlock various pages in a chunk...
sl@0: //
sl@0: TUint   TestChunkingIndex = 0;
sl@0: TUint   TestChunkingIndexFails = 0;
sl@0: 
sl@0: void DoSomeChunking()
sl@0: 	{
sl@0: 	TUint       iters = TEST_NUM_CHUNK_PAGES / 4;
sl@0: 	TBool		lockit = EFalse;
sl@0: 	TBool		decomit = EFalse;
sl@0: 	TUint		index;
sl@0: 	TInt		ret;
sl@0: 	TInt		theOffset;
sl@0: 	
sl@0: 	while (iters)
sl@0: 		{
sl@0: 		TestChunkingIndex = TestChunkingIndex * 69069 + 1;
sl@0: 		index = TUint64((TUint64)TestChunkingIndex*(TUint64)TEST_NUM_CHUNK_PAGES)>>32;
sl@0: 		if (index >= TEST_NUM_CHUNK_PAGES)
sl@0: 			TestChunkingIndexFails ++;
sl@0: 
sl@0: 		theOffset = index * TestPageSize;
sl@0: 		if (theOffset < TestCommitEnd)
sl@0: 			{
sl@0: 			if (lockit)
sl@0: 				{
sl@0: 				if (decomit)
sl@0: 					{
sl@0: 					ret = TestChunk.Decommit(theOffset,TestPageSize);
sl@0: 					if (KErrNone == ret)
sl@0: 						TestChunkStats[index].decommit.ok ++;
sl@0: 					else
sl@0: 						TestChunkStats[index].decommit.fail ++;
sl@0: 					ret = TestChunk.Commit(theOffset,TestPageSize);
sl@0: 					if (KErrNone == ret)
sl@0: 						{
sl@0: 						TestChunkStats[index].commit.ok ++;
sl@0: 						FillPage(theOffset);
sl@0: 						TestChunkPageState[index] = ETrue;
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						TestChunkStats[index].commit.fail ++;
sl@0: 						TestChunkPageState[index] = EFalse;
sl@0: 						}
sl@0: 					ret = KErrNone;
sl@0: 					}
sl@0: 				else
sl@0: 					{
sl@0: 					ret = TestChunk.Lock(theOffset,TestPageSize);
sl@0: 					if (KErrNone == ret)
sl@0: 						{
sl@0: 						TestChunkStats[index].lock.ok ++;
sl@0: 						if (!CheckPage(index, theOffset))
sl@0: 							FillPage(theOffset);
sl@0: 						TestChunkPageState[index] = ETrue;
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						TestChunkStats[index].lock.fail ++;
sl@0: 						TestChunkPageState[index] = EFalse;
sl@0: 						}
sl@0: 					}
sl@0: 				decomit = !decomit;
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				if (TestChunkPageState[index])
sl@0: 					{
sl@0: 					// this one should still be locked so the data should be ok.
sl@0: 					if (KErrNone == TestChunk.Lock(theOffset,TestPageSize))
sl@0: 						{				
sl@0: 						TestChunkStats[index].lock.ok ++;
sl@0: 						CheckPage(index, theOffset);
sl@0: 						}
sl@0: 					else
sl@0: 						TestChunkStats[index].lock.fail ++;
sl@0: 					}
sl@0: 				ret = TestChunk.Unlock(theOffset,TestPageSize);
sl@0: 				if (KErrNone == ret)
sl@0: 					TestChunkStats[index].unlock.ok ++;
sl@0: 				else
sl@0: 					TestChunkStats[index].unlock.fail ++;
sl@0: 				TestChunkPageState[index] = EFalse;
sl@0: 				}
sl@0: 			if (KErrNone != ret)			
sl@0: 				{
sl@0: 				// so now we need to commit another page in this pages place.
sl@0: 				ret = TestChunk.Commit(theOffset,TestPageSize);
sl@0: 				if (KErrNone != ret)
sl@0: 					{
sl@0: 					TestChunkStats[index].commit.fail ++;
sl@0: 					//DBGS_PRINT((_L("%S : DoSomeChunking[%03d] index %03d failed to commit a page  %d\n"), &TestNameBuffer, iters, index, ret));
sl@0: 					TestChunkPageState[index] = EFalse;
sl@0: 					}
sl@0: 				else
sl@0: 					{
sl@0: 					TestChunkStats[index].commit.ok ++;
sl@0: 					FillPage(theOffset);
sl@0: 					TestChunkPageState[index] = ETrue;
sl@0: 					}
sl@0: 				}
sl@0: 			lockit = !lockit;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			RDebug::Printf("DoSomeChunking - offset was bad %d / %d", theOffset, TestCommitEnd);
sl@0: 			}
sl@0: 		iters --;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoMultipleTest
sl@0: // 
sl@0: // Perform the multiple thread test, spawning a number of threads.
sl@0: // It is complicated a little because test.Printf can only be called from the first thread that calls it 
sl@0: // so if we are using multiple threads we need to use a message queue to pass the debug info from the
sl@0: // child threads back to the parent for the parent to then call printf.
sl@0: //
sl@0: 
sl@0: TInt DoMultipleTest(TBool aLowMem = EFalse)
sl@0: 	{
sl@0: 	TInt			 index;
sl@0: 	TUint            start = User::TickCount();
sl@0: 	RThread			*pTheThreads = NULL;
sl@0: 	TInt			*pThreadInUse = NULL;
sl@0: 
sl@0: 	RProcess		*pTheProcesses = NULL;
sl@0: 	TInt			*pProcessInUse = NULL;
sl@0: 
sl@0: 	RThread			*pMedThreads = NULL;
sl@0: 	TInt			*pMedInUse = NULL;
sl@0: 
sl@0: 	TRequestStatus	mediaStatus;
sl@0: 	RThread			mediaThread;
sl@0: 	TInt ret;
sl@0: 
sl@0: 	RSemaphore	*pTheSem = NULL;
sl@0: 
sl@0: 	DisplayTestBanner(ETrue);
sl@0: 	
sl@0: 	TestThreadsExit = EFalse;
sl@0: 
sl@0: 	DOTEST1(ret,TestMultiSem.CreateLocal(1),KErrNone, KErrNoMemory);
sl@0: 	
sl@0: 	pTheSem = &TestMultiSem;
sl@0: 	if (TestLoading & TEST_DLL)
sl@0: 		{
sl@0: 		DOTEST((pTheThreads  = (RThread *)User::AllocZ(sizeof(RThread) * TestMultipleThreadCount)),
sl@0: 		       (pTheThreads != NULL))
sl@0: 		DOTEST((pThreadInUse = (TInt *)User::AllocZ(sizeof(TInt) * TestMultipleThreadCount)),
sl@0: 		       (pThreadInUse != NULL));
sl@0: 		RUNTEST1(pTheThreads && pThreadInUse);
sl@0: 		if (!(pTheThreads && pThreadInUse))
sl@0: 			return KErrGeneral;
sl@0: 		}
sl@0: 
sl@0: 	if (TestLoading & TEST_EXE_SELF)
sl@0: 		{
sl@0: 		DOTEST((pTheProcesses = (RProcess *)User::AllocZ(sizeof(RProcess) * TestMultipleThreadCount)),
sl@0: 		       (pTheProcesses != NULL));
sl@0: 		DOTEST((pProcessInUse = (TInt *)User::AllocZ(sizeof(TInt) * TestMultipleThreadCount)),
sl@0: 		       (pProcessInUse != NULL));
sl@0: 		RUNTEST1(pTheProcesses && pProcessInUse);
sl@0: 		if (!(pTheProcesses && pProcessInUse))
sl@0: 			return KErrGeneral;
sl@0: 		}
sl@0: 	
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		DOTEST1(ret,TestMsgQueue.CreateLocal(TestMultipleThreadCount * 10, EOwnerProcess),KErrNone, KErrNoMemory);
sl@0: 		if (ret != KErrNone)
sl@0: 			return KErrGeneral;
sl@0: 		}
sl@0: 
sl@0: 	if (TestMediaAccess != KTestMediaAccessNone)
sl@0: 		{
sl@0: 		if (TestMediaAccess != KTestMediaAccessBasic)
sl@0: 			{
sl@0: 			TestStopMedia = EFalse;
sl@0: 			DOTEST((pMedThreads  = (RThread *)User::AllocZ(sizeof(RThread) * TestMultipleThreadCount)),
sl@0: 				   (pMedThreads != NULL))
sl@0: 			DOTEST((pMedInUse = (TInt *)User::AllocZ(sizeof(TInt) * TestMultipleThreadCount)),
sl@0: 				   (pMedInUse != NULL));
sl@0: 			RUNTEST1(pMedThreads && pMedInUse);
sl@0: 			if (!(pMedThreads && pMedInUse))
sl@0: 				return KErrGeneral;
sl@0: 
sl@0: 			for (index = 0; index < TestMultipleThreadCount; index++)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("%S : Starting Media Thread %d\n"), &TestNameBuffer, index));
sl@0: 				DOTEST1(ret,pMedThreads[index].Create(KTestBlank,PerformRomAndFileSystemAccess,KDefaultStackSize,NULL,(TAny*) index),KErrNone, KErrNoMemory);
sl@0: 				if (ret == KErrNone)
sl@0: 					{
sl@0: 					pMedThreads[index].Resume();
sl@0: 					pMedInUse[index] = 1;
sl@0: 					}
sl@0: 				User::AfterHighRes(0);
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TestStopMedia = EFalse;
sl@0: 			DOTEST1(ret,mediaThread.Create(KTestBlank,PerformRomAndFileSystemAccess,KDefaultStackSize,NULL,(TAny *) 0),KErrNone, KErrNoMemory);
sl@0: 			if (ret == KErrNone)
sl@0: 				{
sl@0: 				mediaThread.Logon(mediaStatus);
sl@0: 				RUNTEST1(mediaStatus == KRequestPending);	
sl@0: 				mediaThread.Resume();
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	TInt maxDlls = GetNumDlls();
sl@0: 	if (TestLoadDllHow == TEST_DLL_GLOBAL)
sl@0: 		{
sl@0: 		TInt retVal = LoadTheLibs(theGlobalLibs, maxDlls, 0, NULL, NULL, NULL);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("DoMultipleTest - unable to load libs\n")));
sl@0: 			CloseTheLibs (theGlobalLibs, maxDlls);
sl@0: 			if (!TestSilent)
sl@0: 				{
sl@0: 				TestMsgQueue.Close();
sl@0: 				}
sl@0: 			TestMultiSem.Close();
sl@0: 			return KErrGeneral;
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// make sure we have a priority higher than that of the threads we spawn...
sl@0: 	RThread thisThread;
sl@0: 	TThreadPriority savedThreadPriority = thisThread.Priority();
sl@0: 	const TThreadPriority KMainThreadPriority = EPriorityMuchMore;
sl@0: 	__ASSERT_COMPILE(KMainThreadPriority>TEST_INTERLEAVE_PRIO);
sl@0: 	thisThread.SetPriority(KMainThreadPriority);
sl@0: 	
sl@0: 
sl@0: 	for (index = 0; index < TestMultipleThreadCount; index++)
sl@0: 		{
sl@0: 		if (TestLoading & TEST_EXE_SELF)
sl@0: 			{
sl@0: 			if (KErrNone == StartExe(pTheProcesses[index], 0, index + ((TestLoading & TEST_DLL) ? TestMultipleThreadCount : 0), ((TestLoading & TEST_EXE_SELF) == TEST_EXE_SELF) ? (index & 2) : (TestLoading & TEST_SELF), aLowMem, pTheSem))
sl@0: 				{
sl@0: 				User::AfterHighRes(0);
sl@0: 				pProcessInUse[index] = 1;
sl@0: 				}
sl@0: 			}
sl@0: 		
sl@0: 	
sl@0: 		if (TestLoading & TEST_DLL)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("%S : Starting Thread %d\n"), &TestNameBuffer, index));
sl@0: 			DOTEST1(ret,pTheThreads[index].Create(KTestBlank,MultipleTestThread,KDefaultStackSize,NULL,(TAny*) index),KErrNone, KErrNoMemory);
sl@0: 			if (ret == KErrNone)
sl@0: 				{
sl@0: 				pTheThreads[index].Resume();
sl@0: 				User::AfterHighRes(0);
sl@0: 				pThreadInUse[index] = 1;
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// wait for any child threads to exit and process any debug messages they pass back to the parent.
sl@0: 	TBool		anyUsed = ETrue;
sl@0: 	TMessageBuf	localBuffer;
sl@0: 	
sl@0: 	TInt		processOk = 0;
sl@0: 	TInt		threadOk = 0;
sl@0: 	TInt		processPanic = 0;
sl@0: 	TInt		threadPanic = 0;
sl@0: 	TUint		end = start;
sl@0: 	TUint		now;
sl@0: 	TUint		time;
sl@0: 	TUint		killNext = 0;
sl@0: 	TUint		numDots = 0;
sl@0: 	TUint		maxDots = (10*60)/TEST_DOT_PERIOD;	// No individual test should take longer than 10 minutes!
sl@0: 													// Most have been tuned to take between 2 and 8 minutes.
sl@0: 													// The autotests should not take more than 120 minutes total.
sl@0: 
sl@0: 	while(anyUsed)
sl@0: 		{
sl@0: 		TInt threadCount = 0;
sl@0: 		TInt processCount = 0;
sl@0: 		anyUsed = EFalse;
sl@0: 
sl@0: 		// check the message queue and call printf if we get a message.
sl@0: 		if (!TestSilent)
sl@0: 			{
sl@0: 			while (KErrNone == TestMsgQueue.Receive(localBuffer))
sl@0: 				{
sl@0: 				DBGS_PRINT((localBuffer));
sl@0: 				}
sl@0: 			}
sl@0: 
sl@0: 		// walk through the thread list to check which are still alive.
sl@0: 		for (index = 0; index < TestMultipleThreadCount; index++)
sl@0: 			{
sl@0: 			if (TestLoading & TEST_DLL)
sl@0: 				{
sl@0: 				if (pThreadInUse[index])
sl@0: 					{
sl@0: 					if (pTheThreads[index].ExitType() != EExitPending)
sl@0: 						{
sl@0: 						if (pTheThreads[index].ExitType() == EExitPanic)
sl@0: 							{
sl@0: 							DBGS_PRINT((_L("%S : Thread %d Panic'd after %u ticks \n"),
sl@0: 								&TestNameBuffer, index, User::TickCount() - start));	
sl@0: 							threadPanic ++;
sl@0: 							}
sl@0: 						else
sl@0: 							{
sl@0: 							DBGS_PRINT((_L("%S : Thread %d Exited after %u ticks \n"),
sl@0: 								&TestNameBuffer, index, User::TickCount() - start));	
sl@0: 							threadOk ++;
sl@0: 							}
sl@0: 						pTheThreads[index].Close();
sl@0: 						pThreadInUse[index] = EFalse;
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						threadCount += 1;
sl@0: 						anyUsed = ETrue;
sl@0: 						if (TestThreadsExit)
sl@0: 							{
sl@0: 							now = User::TickCount();
sl@0: 							time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 							if (time > TEST_DOT_PERIOD)
sl@0: 								{
sl@0: 								DBGS_PRINT((_L("%S : Thread %d still running\n"), &TestNameBuffer, index));	
sl@0: 								}
sl@0: 							time = TUint((TUint64)(now-killNext)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 							const TUint killTimeStep = (TEST_DOT_PERIOD+9)/10; // 1/10th of a dot
sl@0: 							if(time>TEST_DOT_PERIOD+killTimeStep)
sl@0: 								{
sl@0: 								killNext += killTimeStep*1000000/TickPeriod;
sl@0: 								DBGS_PRINT((_L("%S : killing Thread %d\n"), &TestNameBuffer, index));	
sl@0: 								pTheThreads[index].Kill(KErrNone);
sl@0: 								pTheThreads[index].Close();
sl@0: 								pThreadInUse[index] = EFalse;
sl@0: 								}
sl@0: 							}
sl@0: 						}
sl@0: 					}
sl@0: 				}
sl@0: 			if (TestLoading & TEST_EXE_SELF)
sl@0: 				{
sl@0: 				if (pProcessInUse[index])
sl@0: 					{
sl@0: 					if (pTheProcesses[index].ExitType() != EExitPending)
sl@0: 						{
sl@0: 						if (pTheProcesses[index].ExitType() == EExitPanic)
sl@0: 							{
sl@0: 							DBGS_PRINT((_L("%S : Process %d Panic'd after %u ticks \n"),
sl@0: 								&TestNameBuffer,
sl@0: 								index + ((TestLoading & TEST_DLL) ? TestMultipleThreadCount : 0),
sl@0: 								User::TickCount() - start));	
sl@0: 							processPanic ++;
sl@0: 							}
sl@0: 						else
sl@0: 							{
sl@0: 							DBGS_PRINT((_L("%S : Process %d Exited after %u ticks \n"),
sl@0: 								&TestNameBuffer,
sl@0: 								index + ((TestLoading & TEST_DLL) ? TestMultipleThreadCount : 0),
sl@0: 								User::TickCount() - start));	
sl@0: 							processOk ++;
sl@0: 							}
sl@0: 
sl@0: 						pTheProcesses[index].Close();
sl@0: 						pProcessInUse[index] = EFalse;
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						processCount += 1;
sl@0: 						anyUsed = ETrue;
sl@0: 						if (TestThreadsExit)
sl@0: 							{
sl@0: 							now = User::TickCount();
sl@0: 							time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 							if (time > TEST_DOT_PERIOD)
sl@0: 								{
sl@0: 								DBGS_PRINT((_L("%S : Process %d still running; killing it.\n"),
sl@0: 									&TestNameBuffer, index));
sl@0: 								pTheProcesses[index].Kill(EExitKill);
sl@0: 								pTheProcesses[index].Close();
sl@0: 								pProcessInUse[index] = EFalse;
sl@0: 								}
sl@0: 							
sl@0: 							}
sl@0: 						}
sl@0: 					}
sl@0: 				}
sl@0: 			}
sl@0: 
sl@0: 		now = User::TickCount();
sl@0: 		time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 
sl@0: 		DBGD_PRINT((_L("%S : %d seconds (%d ticks) %d threads, %d processes still alive\n"),
sl@0: 			&TestNameBuffer, time, now, threadCount, processCount));
sl@0: 
sl@0: 		if (time > TEST_DOT_PERIOD)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L(".")));
sl@0: 			numDots ++;
sl@0: 			end += TEST_DOT_PERIOD*1000000/TickPeriod;
sl@0: 			if (TestingReaper)
sl@0: 				{
sl@0: 				TestingReaperCleaningFiles = ETrue;
sl@0: 				CleanupFiles(EFalse);
sl@0: 				CheckFilePresence(ETrue);
sl@0: 				TestingReaperCleaningFiles = EFalse;
sl@0: 				}
sl@0: 			if ((numDots >= maxDots) && (!TestThreadsExit))
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("Taking longer than %d dots...exiting test case."), maxDots));
sl@0: 				TestThreadsExit = ETrue;
sl@0: 				killNext = end;
sl@0: 				}
sl@0: 			}
sl@0: 
sl@0: 		if (TestingChunks)
sl@0: 			{
sl@0: 			DoSomeChunking();
sl@0: 			}
sl@0: 
sl@0: #ifdef TEST_THRASHING_TEST
sl@0: 		User::AfterHighRes(1000);
sl@0: #else
sl@0: 		User::AfterHighRes(TickPeriod);
sl@0: #endif
sl@0: 		}
sl@0: 
sl@0: 	DBGD_PRINT((_L("%S : all test threads presumably gone now\n"), &TestNameBuffer));
sl@0: 
sl@0: 	if (TestMediaAccess != KTestMediaAccessNone)
sl@0: 		{
sl@0: 		if (TestMediaAccess != KTestMediaAccessBasic)
sl@0: 			{
sl@0: 			TBool killMedia = EFalse;
sl@0: 			TestStopMedia = ETrue;
sl@0: 			anyUsed = ETrue;
sl@0: 			DBGS_PRINT((_L("%S : Waiting for media threads to exit...\n"), &TestNameBuffer));	
sl@0: 			end = User::TickCount();
sl@0: 			while (anyUsed)
sl@0: 				{
sl@0: 				anyUsed = EFalse;
sl@0: 
sl@0: 				// check the message queue and call printf if we get a message.
sl@0: 				if (!TestSilent)
sl@0: 					{
sl@0: 					while (KErrNone == TestMsgQueue.Receive(localBuffer))
sl@0: 						{
sl@0: 						DBGS_PRINT((localBuffer));
sl@0: 						}
sl@0: 					}
sl@0: 
sl@0: 				for (index = 0; index < TestMultipleThreadCount; index++)
sl@0: 					{
sl@0: 					if (pMedInUse[index])
sl@0: 						{
sl@0: 						if (pMedThreads[index].ExitType() != EExitPending)
sl@0: 							{
sl@0: 							if (pMedThreads[index].ExitType() == EExitPanic)
sl@0: 								{
sl@0: 								DBGS_PRINT((_L("%S : Media Thread %d Panic'd after %u ticks \n"),
sl@0: 									&TestNameBuffer, index, User::TickCount() - start));	
sl@0: 								threadPanic ++;
sl@0: 								}
sl@0: 							else
sl@0: 								{
sl@0: 								DBGS_PRINT((_L("%S : Media Thread %d Exited after %u ticks \n"),
sl@0: 									&TestNameBuffer, index, User::TickCount() - start));	
sl@0: 								threadOk ++;
sl@0: 								}
sl@0: 							pMedInUse[index] = EFalse;
sl@0: 							}
sl@0: 						else
sl@0: 							{
sl@0: 							anyUsed = ETrue;
sl@0: 							if (killMedia)
sl@0: 								{
sl@0: 								DBGS_PRINT((_L("%S : Media Thread %d still going after %u ticks; killing it!\n"),
sl@0: 									&TestNameBuffer, index, User::TickCount() - start));	
sl@0: 								pMedThreads[index].Kill(EExitKill);
sl@0: 								}
sl@0: 							}
sl@0: 						}
sl@0: 					}
sl@0: 				now = User::TickCount();
sl@0: 				time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 				if (time > TEST_DOT_PERIOD)
sl@0: 					{
sl@0: 					DBGS_PRINT((_L(".")));
sl@0: 					end += TEST_DOT_PERIOD*1000000/TickPeriod;
sl@0: 					killMedia = ETrue;
sl@0: 					}
sl@0: 
sl@0: 				User::AfterHighRes(50000);
sl@0: 
sl@0: 				}
sl@0: 			DBGS_PRINT((_L("%S : Media threads exited...\n"), &TestNameBuffer));	
sl@0: 			User::Free(pMedThreads);
sl@0: 			User::Free(pMedInUse);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TestStopMedia = ETrue;
sl@0: 			DBGS_PRINT((_L("%S : Waiting for media thread to exit...\n"), &TestNameBuffer));	
sl@0: 			end = User::TickCount();
sl@0: 			while (mediaThread.ExitType() == EExitPending)
sl@0: 				{
sl@0: 				now = User::TickCount();
sl@0: 				time = TUint((TUint64)(now-end)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 				if (time > TEST_DOT_PERIOD)
sl@0: 					{
sl@0: 					DBGS_PRINT((_L("%S : Media thread still going after %u seconds; killing it!\n"),
sl@0: 						&TestNameBuffer, time));
sl@0: 					mediaThread.Kill(EExitKill);
sl@0: 					}
sl@0: 				User::AfterHighRes(50000);
sl@0: 				}
sl@0: 			User::WaitForRequest(mediaStatus);
sl@0: 			mediaThread.Close();
sl@0: 			DBGS_PRINT((_L("%S : Media thread exited...\n"), &TestNameBuffer));	
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	DBGD_PRINT((_L("%S : all media threads presumably gone now\n"), &TestNameBuffer));
sl@0: 
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		TestMsgQueue.Close();
sl@0: 		}
sl@0: 	TestMultiSem.Close();
sl@0: 
sl@0: 	DBGD_PRINT((_L("%S : about to close the libraries\n"), &TestNameBuffer));
sl@0: 
sl@0: 	if (TestLoadDllHow == TEST_DLL_GLOBAL)
sl@0: 		{
sl@0: 		CloseTheLibs(theGlobalLibs, maxDlls);
sl@0: 		}
sl@0: 
sl@0: 	TestThreadsExit = EFalse;
sl@0: 
sl@0: 	DBGD_PRINT((_L("%S : cleaning up\n"), &TestNameBuffer));
sl@0: 
sl@0: 	// cleanup the resources and exit.
sl@0: 	if (TestLoading & TEST_EXE_SELF)
sl@0: 		{
sl@0: 		User::Free(pTheProcesses);
sl@0: 		User::Free(pProcessInUse);
sl@0: 		}
sl@0: 
sl@0: 	// cleanup the resources and exit.
sl@0: 	if (TestLoading & TEST_DLL)
sl@0: 		{
sl@0: 		User::Free(pTheThreads);
sl@0: 		User::Free(pThreadInUse);
sl@0: 		}
sl@0: 
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		end = User::TickCount();
sl@0: 		time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 		DBGS_PRINT((_L("\n%S : Multiple Test : (%u seconds)\n\tThreads panic'd = %d Ok = %d\n\tProcess panic'd = %d Ok = %d\n"), &TestNameBuffer, time, threadPanic, threadOk, processPanic, processOk));
sl@0: 		}
sl@0: 
sl@0: 	thisThread.SetPriority(savedThreadPriority);
sl@0: 
sl@0: 	return (threadPanic | processPanic) ? KErrGeneral : KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoChunkTests
sl@0: //
sl@0: // Allocate a chunk and assign some pages to it...
sl@0: // Then do a multiple test.
sl@0: //
sl@0: 
sl@0: void DoChunkTests()
sl@0: 	{
sl@0: 	SVMCacheInfo  tempPages;
sl@0: 	memset(&tempPages, 0, sizeof(tempPages));
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		// Shrink the page cache down to the minimum.
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
sl@0: 
sl@0: 		DBGS_PRINT((_L("Start : min %d max %d current %d maxFree %d freeRam %d\n"),
sl@0: 					 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize, FreeRam()));
sl@0: 
sl@0: 		// set the cache small 
sl@0: 		TInt minSize = 16 * TestPageSize;
sl@0: 		TInt maxSize = TEST_NUM_PAGES * TestPageSize;
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 		}
sl@0: 
sl@0: 	if (KErrNone != TestChunk.CreateDisconnectedLocal(0,0,TEST_NUM_CHUNK_PAGES *TestPageSize))
sl@0: 		{
sl@0: 		DBGS_PRINT((_L("DoChunkTests - create failed.\n")));
sl@0: 		return;
sl@0: 		}
sl@0: 	TestChunkBase = TestChunk.Base();
sl@0: 	if (TestChunkBase == NULL)
sl@0: 		{
sl@0: 		RDebug::Printf("DoChunkTests - TestChunkBase was NULL");
sl@0: 		TestChunk.Close();
sl@0: 		return;
sl@0: 		}
sl@0: 	TInt retVal = KErrNone;
sl@0: 	TUint index = 0;
sl@0: 	TestCommitEnd = 0;
sl@0: 	memset(TestChunkPageState, 0, sizeof(TestChunkPageState));
sl@0: 	memset(TestChunkStats,0,sizeof(TestChunkStats));
sl@0: 	while(index < TEST_NUM_CHUNK_PAGES)
sl@0: 		{
sl@0: 		retVal = TestChunk.Commit(TestCommitEnd,TestPageSize);
sl@0: 		if (KErrNone != retVal)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("%S : TestChunk.Commit returned %d for 0x%08x...\n"), &TestNameBuffer, retVal, TestCommitEnd));	
sl@0: 			break;
sl@0: 			}
sl@0: 		TestChunkPageState[index] = ETrue;
sl@0: 		FillPage(TestCommitEnd);
sl@0: 		TestCommitEnd += TestPageSize;
sl@0: 		index ++;
sl@0: 		}
sl@0: 	RUNTEST1(retVal == KErrNone);
sl@0: 	
sl@0: 	// now do some testing....
sl@0: 	TestingChunks = ETrue;
sl@0: 	TestInterleave = EFalse;
sl@0: 	TestPrioChange = ETrue;
sl@0: 	TestMediaAccess = KTestMediaAccessNone;
sl@0: 	// temp
sl@0: 	TestWhichMedia = TEST_MEDIA_ROM_BASE;
sl@0: 
sl@0: 	if (TestChunksPlus)
sl@0: 		{
sl@0: 		TestMaxLoops = 1;
sl@0: 		TestMultipleThreadCount	= 40;
sl@0: 		}
sl@0: 	else if (TestExtremeChunks)
sl@0: 		{
sl@0: 		TestMaxLoops = 10;
sl@0: 		TestMultipleThreadCount	= 12;
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TestMaxLoops = 3;
sl@0: 		TestMultipleThreadCount	= 20;
sl@0: 		}
sl@0: 	TestWhichTests = TEST_RANDOM;
sl@0: 
sl@0: 	TestLoading = TEST_EXE_SELF_DLL;
sl@0: 	TestLoadDllHow = TEST_DLL_FUNC;
sl@0: 	TestChunkingIndexFails = 0;
sl@0: 
sl@0: 	TEST_NEXT((_L("Multiple threads random with chunks.")));
sl@0: 	RUNTEST(DoMultipleTest(), KErrNone);
sl@0: 	
sl@0: 	TestingChunks = EFalse;
sl@0: 
sl@0: 	// clean up.
sl@0: 	UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0);
sl@0: 	TestChunk.Close();
sl@0: 
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		// put the cache back to the the original values.
sl@0: 		TInt minSize = tempPages.iMinSize;
sl@0: 		TInt maxSize = tempPages.iMaxSize;
sl@0: 
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
sl@0: 
sl@0: 		DBGS_PRINT((_L("Finish : min %d max %d current %d maxFree %d freeRam %d\n"),
sl@0: 					 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize, FreeRam()));
sl@0: 		}
sl@0: 	TChunkTestStats  stats;
sl@0: 
sl@0: 	memset(&stats, 0, sizeof(stats));
sl@0: 	DBGS_PRINT((_L("Stats : (pass/fail) \nindex\t\tlock\t\tunlock\t\tcommit\t\tdecommit\t\tcheck\n")));
sl@0: 	for (index = 0; index < TEST_NUM_CHUNK_PAGES; index ++)
sl@0: 		{
sl@0: 		DBGS_PRINT((_L("%u\t\t%d/%d\t\t%d/%d\t\t%d/%d\t\t%d/%d\t\t%d/%d\n"), 
sl@0: 					index,
sl@0: 					TestChunkStats[index].lock.ok, TestChunkStats[index].lock.fail,
sl@0: 					TestChunkStats[index].unlock.ok, TestChunkStats[index].unlock.fail,
sl@0: 					TestChunkStats[index].commit.ok, TestChunkStats[index].commit.fail,
sl@0: 					TestChunkStats[index].decommit.ok, TestChunkStats[index].decommit.fail,
sl@0: 					TestChunkStats[index].check.ok, TestChunkStats[index].check.fail));
sl@0: 
sl@0: 		stats.lock.ok += TestChunkStats[index].lock.ok;
sl@0: 		stats.lock.fail += TestChunkStats[index].lock.fail;
sl@0: 		stats.unlock.ok += TestChunkStats[index].unlock.ok;
sl@0: 		stats.unlock.fail += TestChunkStats[index].unlock.fail;
sl@0: 		stats.decommit.ok += TestChunkStats[index].decommit.ok;
sl@0: 		stats.decommit.fail += TestChunkStats[index].decommit.fail;
sl@0: 		stats.commit.ok += TestChunkStats[index].commit.ok;
sl@0: 		stats.commit.fail += TestChunkStats[index].commit.fail;
sl@0: 		stats.check.ok += TestChunkStats[index].check.ok;
sl@0: 		stats.check.fail += TestChunkStats[index].check.fail;
sl@0: 		}
sl@0: 
sl@0: 	DBGS_PRINT((_L("Total Stats (p/f): \n\t lock %d / %d\n\t unlock  %d / %d\n\t commit %d / %d\n\t decommit %d / %d\n\t check %d / %d\n"), 
sl@0: 				stats.lock.ok, stats.lock.fail,
sl@0: 				stats.unlock.ok, stats.unlock.fail,
sl@0: 				stats.commit.ok, stats.commit.fail,
sl@0: 				stats.decommit.ok, stats.decommit.fail,
sl@0: 				stats.check.ok, stats.check.fail));
sl@0: 	DBGS_PRINT((_L("TestChunkingIndexFails %d\n"), TestChunkingIndexFails));
sl@0: 
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoReaperTests
sl@0: //
sl@0: // Test the reaper by deleting the transient files and re-creating them.
sl@0: //
sl@0: 
sl@0: void DoReaperTests(void)
sl@0: 	{
sl@0: 	// make sure we have the full complement of files.
sl@0: 	CheckFilePresence(ETrue);
sl@0: 	
sl@0: 	// now do some testing....
sl@0: 	TestInterleave = EFalse;
sl@0: 	TestPrioChange = EFalse;
sl@0: 	TestMediaAccess = KTestMediaAccessNone;
sl@0: 	// temp
sl@0: 	TestWhichMedia = TEST_MEDIA_ALL;
sl@0: 	TestMaxLoops = 3;
sl@0: 	TestMultipleThreadCount	= 12;
sl@0: 	TestWhichTests = TEST_RANDOM;
sl@0: 
sl@0: 	TestLoading = TEST_EXE_SELF_DLL;
sl@0: 	TestLoadDllHow = TEST_DLL_FUNC;
sl@0: 	
sl@0: 	TestingReaper = ETrue;
sl@0: 
sl@0: 	TEST_NEXT((_L("Reaper tests.")));
sl@0: 	RUNTEST(DoMultipleTest(), KErrNone);
sl@0: 	TestInterleave = ETrue;
sl@0: 	TestPrioChange = ETrue;
sl@0: 	TEST_NEXT((_L("Reaper tests 2.")));
sl@0: 	RUNTEST(DoMultipleTest(), KErrNone);
sl@0: 	
sl@0: 	TestingReaper = EFalse;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoBtraceTest
sl@0: //
sl@0: // Test the paging BTrace function.
sl@0: //
sl@0: 
sl@0: void DoBtraceTest(void)
sl@0: 	{
sl@0: #define LE4(a) ((*((a) + 3) << 24) + (*((a) + 2) << 16) + (*((a) + 1) << 8) + *(a))
sl@0: 
sl@0: 	RBTrace bTraceHandle;
sl@0: 	
sl@0: 	TInt r = bTraceHandle.Open();
sl@0: 	test(r == KErrNone);
sl@0: 	
sl@0: 	r = bTraceHandle.ResizeBuffer(0x200000); 
sl@0: 	test(r == KErrNone);
sl@0: 	bTraceHandle.SetFilter(BTrace::EPaging, ETrue);
sl@0: 
sl@0: 	// Enable trace
sl@0: 	bTraceHandle.Empty();
sl@0: 	bTraceHandle.SetMode(RBTrace::EEnable);
sl@0: 	
sl@0: 	TestLoading             = TEST_EXE_SELF_DLL;
sl@0: 	TestWhichMedia          = TEST_MEDIA_ROM_BASE;
sl@0: 	TestMaxLoops            = 2;
sl@0: 	TestMultipleThreadCount = 10;
sl@0: 	TestLoadDllHow          = TEST_DLL_FUNC;
sl@0: 	TestInterleave          = ETrue;
sl@0: 	TestPrioChange          = ETrue;
sl@0: 	TestMediaAccess         = KTestMediaAccessNone;
sl@0: 	TestWhichTests          = TEST_RANDOM;		
sl@0: 	TestingLowMem			= EFalse;
sl@0: 
sl@0: 	RUNTEST(DoMultipleTest(TestingLowMem), KErrNone);
sl@0: 
sl@0: 	bTraceHandle.SetMode(0);
sl@0: 
sl@0: 	// analyse the btrace logs and display on the serial port.
sl@0: 	TUint8* pDataStart;
sl@0: 	TInt	dataSize;
sl@0: 	TUint8* pTemp;
sl@0: 	TUint8* pThis;
sl@0: 	TUint8* pEnd;
sl@0: 	TBuf<128>	data;
sl@0: 	while (1)
sl@0: 		{
sl@0: 		dataSize = bTraceHandle.GetData(pDataStart);
sl@0: 		if (dataSize <= 0)
sl@0: 			{
sl@0: 			break;
sl@0: 			}
sl@0: 		pEnd = pDataStart + dataSize;
sl@0: 		pTemp = pDataStart;
sl@0: 		while (pTemp < pEnd)
sl@0: 			{
sl@0: 			TUint8	recSize		= pTemp[BTrace::ESizeIndex];
sl@0: 			TUint8	recFlags	= pTemp[BTrace::EFlagsIndex];
sl@0: 			TUint8	recCat		= pTemp[BTrace::ECategoryIndex];
sl@0: 			TUint8	recSub		= pTemp[BTrace::ESubCategoryIndex];
sl@0: 			TUint32 addr[4];
sl@0: 			pThis = pTemp;
sl@0: 
sl@0: 			data.Zero();
sl@0: 			// step over the header.
sl@0: 			data.Format(_L("size %d cat %d sub %d flg 0x%02x "), recSize, recCat, recSub, recFlags);
sl@0: 			pTemp += 4; 
sl@0: 					
sl@0: 			if (recFlags & BTrace::EHeader2Present)
sl@0: 				{
sl@0: 				data.AppendFormat(_L("h2 0x%08x "), LE4(pTemp));
sl@0: 				pTemp += 4;
sl@0: 				}
sl@0: 			if (recFlags & BTrace::ETimestampPresent)
sl@0: 				{
sl@0: 				data.AppendFormat(_L("ts 0x%08x "), LE4(pTemp));
sl@0: 				pTemp += 4;
sl@0: 				}
sl@0: 			if (recFlags & BTrace::ETimestamp2Present)
sl@0: 				{
sl@0: 				data.AppendFormat(_L("ts2 0x%08x "), LE4(pTemp));
sl@0: 				pTemp += 4;
sl@0: 				}
sl@0: 			if (recFlags & BTrace::EContextIdPresent)
sl@0: 				{
sl@0: 				data.AppendFormat(_L("cId 0x%08x "), LE4(pTemp));
sl@0: 				pTemp += 4;
sl@0: 				}
sl@0: 			TInt index;
sl@0: 			for (index = 0; index < 4; index ++)
sl@0: 				{
sl@0: 				if (recSize > pTemp - pThis)
sl@0: 					{
sl@0: 					addr[index] = LE4(pTemp);
sl@0: 					pTemp += 4;
sl@0: 					}
sl@0: 				else
sl@0: 					addr[index] = 0;
sl@0: 				}
sl@0: 
sl@0: 			switch(recCat)
sl@0: 				{
sl@0: 				case BTrace::EPaging:
sl@0: 					{
sl@0: 					switch (recSub)
sl@0: 						{
sl@0: 						case BTrace::EPagingPageInBegin:
sl@0: 						/**
sl@0: 						- 4 bytes containing the virtual address which was accessed, causing this paging event.
sl@0: 						- 4 bytes containing the virtual address of the instuction which caused this paging event.
sl@0: 						  (The PC value.)
sl@0: 						**/
sl@0: 						test.Printf(_L("PageInBegin    : %S addr 0x%08x inst 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 0 bytes. (No extra data.)
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageInUnneeded:
sl@0: 						test.Printf(_L("PageInUnneeded : %S\n"), &data);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page 'paged in'.
sl@0: 						- 4 bytes containing the virtual address of the page 'paged in'.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageInROM:
sl@0: 						test.Printf(_L("PageInROM      : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being 'paged out'.
sl@0: 						- 4 bytes containing the virtual address of the page being 'paged out'.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageOutROM:
sl@0: 						test.Printf(_L("PageOutROM     : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being 'paged in'.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageInFree:
sl@0: 						test.Printf(_L("PageInFree     : %S phys 0x%08x\n"), &data, addr[0]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being 'paged out'.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageOutFree:
sl@0: 						test.Printf(_L("PageOutFree    : %S phys 0x%08x\n"), &data, addr[0]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being rejuvenated, (made young).
sl@0: 						- 4 bytes containing the virtual address which was accessed, causing this paging event.
sl@0: 						- 4 bytes containing the virtual address of the instuction which caused this paging event.
sl@0: 						  (The PC value.)
sl@0: 						*/
sl@0: 						case BTrace::EPagingRejuvenate:
sl@0: 						test.Printf(_L("Rejuvenate     : %S phys 0x%08x virt 0x%08x inst 0x%08x\n"), &data, addr[0], addr[1], addr[2]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page accessed.
sl@0: 						- 4 bytes containing the virtual address which was accessed, causing this paging event.
sl@0: 						- 4 bytes containing the virtual address of the instuction which caused this paging event.
sl@0: 						  (The PC value.)
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageNop:
sl@0: 						test.Printf(_L("PageNop        : %S phys 0x%08x virt 0x%08x inst 0x%08x\n"), &data, addr[0], addr[1], addr[2]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being locked.
sl@0: 						- 4 bytes containing the value of the lock count after the paged was locked.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageLock:
sl@0: 						test.Printf(_L("PageLock       : %S phys 0x%08x lock 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being unlocked.
sl@0: 						- 4 bytes containing the value of the lock count before the paged was unlocked.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageUnlock:
sl@0: 						test.Printf(_L("PageUnlock     : %S phys 0x%08x lock 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 		
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being 'paged out'.
sl@0: 						- 4 bytes containing the virtual address of the page being 'paged out'.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageOutCache:
sl@0: 						test.Printf(_L("PageOutCache   : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 		
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page 'paged in'.
sl@0: 						- 4 bytes containing the virtual address of the page 'paged in'.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageInCode:
sl@0: 						test.Printf(_L("PageInCode     : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being 'paged out'.
sl@0: 						- 4 bytes containing the virtual address of the page being 'paged out'.
sl@0: 						*/
sl@0: 						case BTrace::EPagingPageOutCode:
sl@0: 						test.Printf(_L("PageOutCode    : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 		
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page 'paged in'.
sl@0: 						- 4 bytes containing the virtual address of the page 'paged in'.
sl@0: 						*/
sl@0: 						case BTrace::EPagingMapCode:
sl@0: 						test.Printf(_L("MapCode        : %S phys 0x%08x virt 0x%08x\n"), &data, addr[0], addr[1]);
sl@0: 						break;
sl@0: 						
sl@0: 						/**
sl@0: 						- 4 bytes containing the physical address of the page being aged, (made old).
sl@0: 						*/
sl@0: 						case BTrace::EPagingAged:
sl@0: 						test.Printf(_L("Aged           : %S phys 0x%08x\n"), &data, addr[0]);
sl@0: 						break;
sl@0: 						}
sl@0: 					}
sl@0: 				break;
sl@0: 
sl@0: 				default:
sl@0: 				
sl@0: 				break;
sl@0: 				}
sl@0: 			pTemp = BTrace::NextRecord(pThis);
sl@0: 			}
sl@0: 		bTraceHandle.DataUsed();
sl@0: 		}
sl@0: 	bTraceHandle.Close();
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // ParseCommandLine 
sl@0: //
sl@0: // read the arguments passed from the command line and set global variables to 
sl@0: // control the tests.
sl@0: //
sl@0: 
sl@0: TBool ParseCommandLine()
sl@0: 	{
sl@0: 	TBuf<256> args;
sl@0: 	User::CommandLine(args);
sl@0: 	TLex	lex(args);
sl@0: 	TBool	retVal = ETrue;
sl@0: 	
sl@0: 	// initially test for arguments, the parse them, if not apply some sensible defaults.
sl@0: 	TBool	foundArgs = EFalse;	
sl@0: 		
sl@0: 	FOREVER
sl@0: 		{
sl@0: 		TPtrC  token=lex.NextToken();
sl@0: 		if(token.Length()!=0)
sl@0: 			{
sl@0: 			if ((token == _L("help")) || (token == _L("-h")) || (token == _L("-?")))
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("\nUsage: [ single | multiple <numThreads>] [ dll | exe | self | complete ] [func | thread | global ] [ rom | base | mixed | mall ] [reaper] [chunks|echunks|chunks+ {nochunkdata}] [prio] [media] [lowmem] [forward | backward | random | all] [loadGlobal | loadThread | loadFunc] [interleave] [d_exc] [btrace] [defrag] [noclean] [min <pages>] [max <pages>] [stressfree] [iters <iters>]\n'-' indicated infinity.\n\n")));
sl@0: 				test.Getch();
sl@0: 				}
sl@0: 			else  if (token == _L("mmc"))
sl@0: 				{
sl@0: 				TestOnlyFromMmc = ETrue;
sl@0: 				}
sl@0: 			else  if (token == _L("min"))
sl@0: 				{
sl@0: 				TPtrC val=lex.NextToken();
sl@0: 				TLex lexv(val);
sl@0: 				TInt value;
sl@0: 				lexv.Val(value);
sl@0: 				TestMinCacheSize = value * 4096;
sl@0: 				}
sl@0: 			else  if (token == _L("max"))
sl@0: 				{
sl@0: 				TPtrC val=lex.NextToken();
sl@0: 				TLex lexv(val);
sl@0: 				TInt value;
sl@0: 				lexv.Val(value);
sl@0: 				TestMaxCacheSize = value * 4096;
sl@0: 				}
sl@0: 			else  if (token == _L("interleave"))
sl@0: 				{
sl@0: 				TestInterleave = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("auto"))
sl@0: 				{
sl@0: 				TestFullAutoTest = EFalse;
sl@0: 				retVal = EFalse;
sl@0: 				}
sl@0: 			else if (token == _L("stressfree"))
sl@0: 				{
sl@0: 				TestStressFree = !TestStressFree;
sl@0: 				retVal = EFalse;
sl@0: 				}
sl@0: 			else if (token == _L("fullauto"))
sl@0: 				{
sl@0: 				TestFullAutoTest = ETrue;
sl@0: 				retVal = EFalse;
sl@0: 				}
sl@0: 			else if (token == _L("prio"))
sl@0: 				{
sl@0: 				TestPrioChange = !TestPrioChange;
sl@0: 				}
sl@0: 			else if (token == _L("media"))
sl@0: 				{
sl@0: 				TestMediaAccess = KTestMediaAccessBasic;
sl@0: 				}
sl@0: 			else if (token == _L("reaper"))
sl@0: 				{
sl@0: 				TestReaper = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("btrace"))
sl@0: 				{
sl@0: 				TestBtrace = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("defrag"))
sl@0: 				{
sl@0: 				TestDefrag = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("echunks"))
sl@0: 				{
sl@0: 				TestChunks = ETrue;
sl@0: 				TestExtremeChunks = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("chunks+"))
sl@0: 				{
sl@0: 				TestChunks = ETrue;
sl@0: 				TestChunksPlus = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("chunks"))
sl@0: 				{
sl@0: 				TestChunks = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("nochunkdata"))
sl@0: 				{
sl@0: 				TestChunkData = EFalse;
sl@0: 				}
sl@0: 			else if (token == _L("lowmem"))
sl@0: 				{
sl@0: 				TestLowMem = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("dll"))
sl@0: 				{
sl@0: 				TestLoading = TEST_DLL;
sl@0: 				}
sl@0: 			else if (token == _L("exe"))
sl@0: 				{
sl@0: 				TestLoading = TEST_EXE;
sl@0: 				}
sl@0: 			else if (token == _L("self"))
sl@0: 				{
sl@0: 				TestLoading = TEST_SELF;
sl@0: 				}
sl@0: 			else if (token == _L("complete"))
sl@0: 				{
sl@0: 				TestLoading |= TEST_EXE_SELF_DLL;
sl@0: 				}
sl@0: 			else if (token == _L("rom"))
sl@0: 				{
sl@0: 				TestWhichMedia = TEST_MEDIA_ROM;
sl@0: 				}
sl@0: 			else if (token == _L("base"))
sl@0: 				{
sl@0: 				TestWhichMedia = TEST_MEDIA_BASE;
sl@0: 				}
sl@0: 			else if (token == _L("mixed"))
sl@0: 				{
sl@0: 				TestWhichMedia |= TEST_MEDIA_ROM_BASE;
sl@0: 				}
sl@0: 			else if (token == _L("all_media"))
sl@0: 				{
sl@0: 				TestWhichMedia |= TEST_MEDIA_ALL;
sl@0: 				}
sl@0: 			else if (token == _L("debug"))
sl@0: 				{
sl@0: 				if (!TestSilent)
sl@0: 					{
sl@0: 					TestDebug = ETrue;
sl@0: 					TestPrioChange = ETrue;
sl@0: 					}
sl@0: 				}
sl@0: 			else if (token == _L("silent"))
sl@0: 				{
sl@0: 				TestSilent = ETrue;
sl@0: 				TestDebug = EFalse;
sl@0: 				}
sl@0: 			else if (token == _L("noclean"))
sl@0: 				{
sl@0: 				TestNoClean = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("d_exc"))
sl@0: 				{
sl@0: 				TestD_Exc = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("global"))
sl@0: 				{
sl@0: 				TestLoadDllHow = TEST_DLL_GLOBAL;
sl@0: 				}	
sl@0: 			else if (token == _L("thread"))
sl@0: 				{
sl@0: 				TestLoadDllHow = TEST_DLL_THREAD;
sl@0: 				}	
sl@0: 			else if (token == _L("func"))
sl@0: 				{
sl@0: 				TestLoadDllHow = TEST_DLL_FUNC;
sl@0: 				}	
sl@0: 			else if (token == _L("single"))
sl@0: 				{
sl@0: 				TestSingle = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("multiple"))
sl@0: 				{
sl@0: 				TPtrC val=lex.NextToken();
sl@0: 				TLex lexv(val);
sl@0: 				TInt value;
sl@0: 
sl@0: 				if (lexv.Val(value)==KErrNone)
sl@0: 					{
sl@0: 					if ((value <= 0) || (value > 100))
sl@0: 						{
sl@0: 						TestMultipleThreadCount = 10;
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						TestMultipleThreadCount = value;
sl@0: 						}
sl@0: 					}
sl@0: 				else
sl@0: 					{
sl@0: 					DBGS_PRINT((_L("Bad value for thread count '%S' was ignored.\n"), &val));
sl@0: 					retVal = EFalse;
sl@0: 					break;
sl@0: 					}
sl@0: 				TestMultiple = ETrue;
sl@0: 				}
sl@0: 			else if (token == _L("forward"))
sl@0: 				{
sl@0: 				TestWhichTests = TEST_FORWARD;
sl@0: 				}
sl@0: 			else if (token == _L("backward"))
sl@0: 				{
sl@0: 				TestWhichTests = TEST_BACKWARD;
sl@0: 				}
sl@0: 			else if (token == _L("random"))
sl@0: 				{
sl@0: 				TestWhichTests = TEST_RANDOM;
sl@0: 				}
sl@0: 			else if (token == _L("all"))
sl@0: 				{
sl@0: 				TestWhichTests = TEST_ALL;
sl@0: 				}
sl@0: 			else  if (token == _L("inst"))
sl@0: 				{
sl@0: 				TPtrC val=lex.NextToken();
sl@0: 				TLex lexv(val);
sl@0: 				TInt value;
sl@0: 
sl@0: 				if (lexv.Val(value)==KErrNone)
sl@0: 					{
sl@0: 					TestInstanceId = value;
sl@0: 					}
sl@0: 				}
sl@0: 			else  if (token == _L("iters"))
sl@0: 				{
sl@0: 				TPtrC val=lex.NextToken();
sl@0: 				TLex lexv(val);
sl@0: 				TInt value;
sl@0: 
sl@0: 				if (val==_L("-"))
sl@0: 					{
sl@0: 					TestMaxLoops = KMaxTInt;
sl@0: 					}
sl@0: 				else
sl@0: 					{
sl@0: 					if (lexv.Val(value)==KErrNone)
sl@0: 						{
sl@0: 						TestMaxLoops = value;
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						DBGS_PRINT((_L("Bad value for thread count '%S' was ignored.\n"), &val));
sl@0: 						retVal = EFalse;
sl@0: 						break;
sl@0: 						}
sl@0: 					}
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				if ((foundArgs == EFalse) && (token.Length() == 1))
sl@0: 					{
sl@0: 					// Single letter argument...only run on 'd'
sl@0: 					if (token.CompareF(_L("d")) == 0)
sl@0: 						{
sl@0: 
sl@0: 						TestFullAutoTest = EFalse;
sl@0: 						TestIsAutomated = ETrue;
sl@0: 						break;
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						if (!TestSilent)
sl@0: 							{
sl@0: 							test.Title();
sl@0: 							test.Start(_L("Skipping non drive 'd' - Test Exiting."));
sl@0: 							test.End();
sl@0: 							}
sl@0: 						foundArgs = ETrue;
sl@0: 						TestExit = ETrue;
sl@0: 						break;
sl@0: 						}
sl@0: 					}
sl@0: 				DBGS_PRINT((_L("Unknown argument '%S' was ignored.\n"), &token));
sl@0: 				break;
sl@0: 				}
sl@0: 			foundArgs = ETrue;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			break;
sl@0: 			}
sl@0: 		}
sl@0: 	if (!foundArgs)
sl@0: 		{
sl@0: 		retVal = EFalse;
sl@0: 		}
sl@0: 	return retVal;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // AreWeTheTestBase
sl@0: //
sl@0: // Test whether we are the root of the tests.
sl@0: //
sl@0: void AreWeTheTestBase()
sl@0: 	{
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		TFileName  filename(RProcess().FileName());
sl@0: 
sl@0: 		TParse	myParse;
sl@0: 		myParse.Set(filename, NULL, NULL);
sl@0: 		TestNameBuffer.Zero();
sl@0: 		TestNameBuffer.Append(myParse.Name());
sl@0: 		TestNameBuffer.Append(_L(".exe"));
sl@0: 
sl@0: 		TestWeAreTheTestBase = !TestNameBuffer.Compare(TestPlExeNames[KTestMediaBase]);
sl@0: 
sl@0: 		RFs fs;
sl@0: 		if (KErrNone == fs.Connect())
sl@0: 			{
sl@0: 			TEntry  anEntry;
sl@0: 			TInt retVal = fs.Entry(_L("z:\\test\\mmcdemandpaginge32tests.bat"), anEntry);
sl@0: 			if (retVal == KErrNone)
sl@0: 				{
sl@0: 				TestBootedFromMmc = ETrue;
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				TestBootedFromMmc = EFalse;
sl@0: 				}
sl@0: 			fs.Close();
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TestNameBuffer.Zero();
sl@0: 		TestNameBuffer.Append(_L("t_pageldrtst.exe"));
sl@0: 		}
sl@0: 	}
sl@0: #define  MEDNONE	KTestMediaAccessNone
sl@0: #define MEDBASIC	KTestMediaAccessBasic
sl@0: #define MEDMTHRE	KTestMediaAccessMultipleThreads
sl@0: #define MEDMPATT	KTestMediaAccessMultiplePattern
sl@0: #define MEDMIX		KTestMediaAccessMixed
sl@0: 
sl@0: TTheTests TheAutoTests[] =
sl@0: 	{// fullOnly,           loading,               media,  multi, loops, threads,         loadHow,  inter,   prio,    media,  whichTests, lowmem, free, testName
sl@0: #ifdef TEST_SHORT_TEST
sl@0: 		{ EFalse,          TEST_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      24,   TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL Load (ALL Media) Multiple thread all."), },
sl@0: #else
sl@0: 		{ EFalse,          TEST_DLL,     TEST_MEDIA_BASE,  ETrue,     5,      24,   TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_THRASH, EFalse,    0, }, //_L("DLL Load (ROM) Multiple thread Thrash."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     5,      20,   TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_ALL,    EFalse,    0, }, //_L("DLL Load (ROM/ROFS) Single thread all."), },
sl@0: 		{  ETrue,          TEST_EXE, TEST_MEDIA_ROM_BASE, EFalse,     5,      20,   TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_ALL,    EFalse,    0, }, //_L("Exe Load (ROM/ROFS) Single thread."), },
sl@0: 		{  ETrue,         TEST_SELF, TEST_MEDIA_ROM_BASE, EFalse,     5,      20,   TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_ALL,    EFalse,    0, }, //_L("Self Load (ROM/ROFS) Single thread."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE,  ETrue,     5,      20,   TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL Load (ROM/ROFS) Multiple thread all."), },
sl@0: 		{ EFalse,          TEST_DLL,      TEST_MEDIA_ALL,  ETrue,     3,      20,   TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL Load (ALL Media) Multiple thread all."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16,   TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16,   TEST_DLL_FUNC, EFalse,  ETrue,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with prio."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      10,   TEST_DLL_FUNC, EFalse, EFalse, MEDBASIC, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with media access."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      12,   TEST_DLL_FUNC, EFalse,  ETrue, MEDBASIC, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with media access and prio."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16, TEST_DLL_THREAD, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load thread (All Media) Multiple threads."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16, TEST_DLL_THREAD, EFalse,  ETrue,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load thread (All Media) Multiple threads with prio."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      12, TEST_DLL_THREAD, EFalse,  ETrue, MEDBASIC, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load thread (All Media) Multiple threads with media access and prio."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16, TEST_DLL_GLOBAL, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load global (All Media) Multiple threads."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16, TEST_DLL_GLOBAL, EFalse,  ETrue,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load global (All Media) Multiple threads with prio."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      12, TEST_DLL_GLOBAL, EFalse,  ETrue, MEDBASIC, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load global (All Media) Multiple threads with media access and prio."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16,   TEST_DLL_FUNC,  ETrue, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16,   TEST_DLL_FUNC,  ETrue,  ETrue,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, prio."), },
sl@0: 
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      16,   TEST_DLL_FUNC,  ETrue,  ETrue, MEDBASIC, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, media and prio."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      12,   TEST_DLL_FUNC,  ETrue,  ETrue, MEDMTHRE, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, multi media and prio."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      12,   TEST_DLL_FUNC,  ETrue,  ETrue, MEDMPATT, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, media and prio."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL,      TEST_MEDIA_ALL,  ETrue,     2,      12,   TEST_DLL_FUNC,  ETrue,  ETrue,   MEDMIX, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load (All Media) Multiple threads with interleave, media and prio."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE,  ETrue,     2,      10,   TEST_DLL_FUNC,  ETrue,  ETrue,   MEDMIX, TEST_RANDOM, EFalse,    0, }, //_L("DLL/EXE/SELF Load Multiple threads with interleave, media and prio."), },
sl@0: #endif // TEST_SHORT_TEST
sl@0: 	};
sl@0: #define NUM_AUTO_TESTS (TInt)(sizeof(TheAutoTests) / sizeof(TTheTests))
sl@0: 
sl@0: //
sl@0: // PerformAutoTest
sl@0: //
sl@0: // The autotest.
sl@0: //
sl@0: 
sl@0: void PerformAutoTest(TBool aReduceTime = EFalse)
sl@0: 	{
sl@0: 	TInt        testIndex;
sl@0: 	TTheTests  *pTest = &TheAutoTests[0];
sl@0: 	
sl@0: 	DoStats();
sl@0: 
sl@0: 	for (testIndex = 0; testIndex < NUM_AUTO_TESTS; testIndex ++, pTest++)
sl@0: 		{
sl@0: 		if (   (   !TestWeAreTheTestBase 
sl@0: 			    && (   (pTest->testLoadDllHow != TEST_DLL_FUNC)
sl@0: 				    || !pTest->testMultiple))
sl@0: 			|| ((TestFullAutoTest == EFalse) && (pTest->testFullAutoOnly)))
sl@0: 			{
sl@0: 			continue;
sl@0: 			}
sl@0: 		
sl@0: 		TestLoading             = pTest->testLoading;
sl@0: 		TestWhichMedia          = pTest->testWhichMedia;
sl@0: 		TestMaxLoops            = aReduceTime ? 1 : pTest->testMaxLoops;
sl@0: 		TestMultipleThreadCount = aReduceTime ? 10 : pTest->testMultipleThreadCount;
sl@0: 		TestLoadDllHow          = pTest->testLoadDllHow;
sl@0: 		TestInterleave          = pTest->testInterleave;
sl@0: 		TestPrioChange          = pTest->testPrioChange;
sl@0: 		TestMediaAccess         = pTest->testMediaAccess;
sl@0: 		if (aReduceTime && (TestMediaAccess != MEDBASIC) && (TestMediaAccess != MEDNONE))
sl@0: 			{
sl@0: 			continue;
sl@0: 			}
sl@0: 		TestWhichTests          = pTest->testWhichTests;		
sl@0: 		TestingLowMem			= pTest->testLowMem;
sl@0: 		if (!TestSilent)
sl@0: 			{
sl@0: 			test.Next(_L("Auto Test"));
sl@0: 			}
sl@0: 		if (pTest->testMultiple)
sl@0: 			{
sl@0: 			RUNTEST(DoMultipleTest(ETrue), KErrNone);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			RUNTEST(DoSingleTest(ETrue), KErrNone);
sl@0: 			}
sl@0: 
sl@0: 		DoStats();
sl@0: 
sl@0: #ifdef TEST_KERN_HEAP
sl@0: 		__KHEAP_MARK;
sl@0: 		__KHEAP_CHECK(0);
sl@0: 		__KHEAP_MARKEND;
sl@0: #endif
sl@0: 		}
sl@0: #ifdef TEST_KERN_HEAP
sl@0: 	__KHEAP_MARK;
sl@0: 	__KHEAP_CHECK(0);
sl@0: 	__KHEAP_MARKEND;
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: TTheTests TheLowMemTests[] =
sl@0: 	{// fullOnly,           loading,               media,  multi, loops, threads,       loadHow,  inter,   prio,    media,  whichTests, lowmem, free, testName
sl@0: #ifndef TEST_SHORT_TEST
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, EFalse,     1,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Single thread with Low memory (init)."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE, EFalse,     5,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM,  ETrue,    0, }, //_L("Single thread with Low memory."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     1,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory (init)."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE,  ETrue,     2,      16, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory ."), },
sl@0: 		{ EFalse,          TEST_DLL, TEST_MEDIA_ALL,      EFalse,     5,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory and All media(init)."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL,       ETrue,     2,      12, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory and All media."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     1,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory, with starting free ram (init)."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE,  ETrue,     2,      16, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM,  ETrue,   32, }, //_L("Multiple thread with Low memory, with starting free ram."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     1,      16, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory and prio and media access(init)."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE,  ETrue,     2,      16, TEST_DLL_FUNC, EFalse,  ETrue, MEDBASIC, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory and prio and media access."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     1,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory interleave, prio and media access(init)."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE,  ETrue,     2,      16, TEST_DLL_FUNC,  ETrue,  ETrue, MEDBASIC, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory interleave, prio and media access."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     1,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory interleave, media access and All media (init)."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL,       ETrue,     2,      16, TEST_DLL_FUNC,  ETrue, EFalse, MEDBASIC, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory interleave, media access and All media + loading."), },
sl@0: 		{ EFalse,		   TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,    10,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Single thread with Low memory (init)."), },
sl@0: 		{ EFalse,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     5,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM,  ETrue,    0, }, //_L("Single thread with Low memory."), },
sl@0: #endif //TEST_SHORT_TEST
sl@0: 		{ EFalse,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,    10,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media (init)."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE,  ETrue,     2,      16, TEST_DLL_FUNC,  ETrue,  ETrue, MEDBASIC, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media + loading."), },
sl@0: 		{ EFalse,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     5,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media (init)."), },
sl@0: 		{ EFalse, TEST_EXE_SELF_DLL, TEST_MEDIA_ROM_BASE,  ETrue,     2,      10, TEST_DLL_FUNC,  ETrue,  ETrue, MEDMTHRE, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory interleave, prio, multi media access and All media + loading."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     1,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media (init)."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL,       ETrue,     2,      16, TEST_DLL_FUNC,  ETrue,  ETrue, MEDBASIC, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media + loading."), },
sl@0: 		{  ETrue,          TEST_DLL, TEST_MEDIA_ROM_BASE, EFalse,     1,       1, TEST_DLL_FUNC, EFalse, EFalse,  MEDNONE, TEST_RANDOM, EFalse,    0, }, //_L("Multiple thread with Low memory interleave, prio, media access and All media (init)."), },
sl@0: 		{  ETrue, TEST_EXE_SELF_DLL, TEST_MEDIA_ALL,       ETrue,     2,      16, TEST_DLL_FUNC,  ETrue,  ETrue, MEDMTHRE, TEST_RANDOM,  ETrue,    0, }, //_L("Multiple thread with Low memory interleave, prio, multi media access and All media + loading."), },
sl@0: 
sl@0: 	};
sl@0: #define NUM_LOWMEM_TESTS (TInt)(sizeof(TheLowMemTests) / sizeof(TTheTests))
sl@0: 
sl@0: //
sl@0: // DoLowMemTest
sl@0: //
sl@0: // Low Memory Test
sl@0: //
sl@0: void DoLowMemTest(TBool aEnableAllMedia = EFalse)
sl@0: 	{
sl@0: 	TInt r = User::LoadLogicalDevice(KPageStressTestLddName);
sl@0: 	RUNTEST1(r==KErrNone || r==KErrAlreadyExists);
sl@0: 	RUNTEST(PagestressLdd.Open(),KErrNone);
sl@0: 	RUNTEST(PagestressLdd.DoSetDebugFlag((TInt)TestDebug),KErrNone);
sl@0: 	
sl@0: 	SVMCacheInfo  tempPages;
sl@0: 	memset(&tempPages, 0, sizeof(tempPages));
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		// get the old cache info
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
sl@0: 		TInt minSize = 8 * 4096;
sl@0: 		TInt maxSize = 256 * 4096;
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 		}
sl@0: 
sl@0: 	TInt		testIndex;
sl@0: 	TTheTests  *pTest = &TheLowMemTests[0];
sl@0: 	for (testIndex = 0; testIndex < NUM_LOWMEM_TESTS; testIndex ++, pTest++)
sl@0: 		{
sl@0: 		if (   (!aEnableAllMedia && (pTest->testWhichMedia == TEST_MEDIA_ALL))
sl@0: 		    || ((TestFullAutoTest == EFalse) && (pTest->testFullAutoOnly)))
sl@0: 			{
sl@0: 			continue;
sl@0: 			}
sl@0: 
sl@0: 		TestLoading             = pTest->testLoading;
sl@0: 		TestWhichMedia          = pTest->testWhichMedia;
sl@0: 		TestMaxLoops            = pTest->testMaxLoops;
sl@0: 		TestMultipleThreadCount = pTest->testMultipleThreadCount;
sl@0: 		TestLoadDllHow          = pTest->testLoadDllHow;
sl@0: 		TestInterleave          = pTest->testInterleave;
sl@0: 		TestPrioChange          = pTest->testPrioChange;
sl@0: 		TestMediaAccess         = pTest->testMediaAccess;
sl@0: 		TestWhichTests          = pTest->testWhichTests;		
sl@0: 		TestingLowMem			= pTest->testLowMem;
sl@0: 		if (!TestSilent)
sl@0: 			{
sl@0: 			test.Next(_L("Low Memory"));
sl@0: 			}
sl@0: 		if (pTest->testLowMem)
sl@0: 			{
sl@0: 			PagestressLdd.DoConsumeRamSetup(pTest->testFreeRam, TEST_LM_BLOCKSIZE);
sl@0: 			}
sl@0: 
sl@0: 		if (pTest->testMultiple)
sl@0: 			{
sl@0: 			RUNTEST(DoMultipleTest(pTest->testLowMem), KErrNone);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			RUNTEST(DoSingleTest(pTest->testLowMem), KErrNone);
sl@0: 			}
sl@0: 
sl@0: 		if (pTest->testLowMem)
sl@0: 			{
sl@0: 			PagestressLdd.DoConsumeRamFinish();
sl@0: 			}
sl@0: 
sl@0: 		DoStats();
sl@0: #ifdef TEST_KERN_HEAP
sl@0: 		__KHEAP_MARK;
sl@0: 		__KHEAP_CHECK(0);
sl@0: 		__KHEAP_MARKEND;
sl@0: #endif
sl@0: 		}
sl@0: 
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		test.Next(_L("Close test driver"));
sl@0: 		}
sl@0: 	PagestressLdd.Close();
sl@0: 	RUNTEST(User::FreeLogicalDevice(KPageStressTestLddName), KErrNone);
sl@0: 
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		TInt minSize = tempPages.iMinSize;
sl@0: 		TInt maxSize = tempPages.iMaxSize;
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 		}
sl@0: 
sl@0: #ifdef TEST_KERN_HEAP
sl@0: 	__KHEAP_MARK;
sl@0: 	__KHEAP_CHECK(0);
sl@0: 	__KHEAP_MARKEND;
sl@0: #endif
sl@0: 	TestingLowMem = EFalse;
sl@0: 
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // MultipleDefragThread
sl@0: //
sl@0: // Thread function, one created for each zone in a multiple thread test.
sl@0: //
sl@0: 
sl@0: LOCAL_C TInt MultipleDefragThread(TAny* aUseTb)
sl@0: 	{
sl@0: 	TInt numZones = 1;
sl@0: 	TInt zoneId = (TInt)aUseTb;
sl@0: 
sl@0: 	if (TestZoneCount > TEST_MAX_ZONE_THREADS)
sl@0: 		{
sl@0: 		numZones = TestZoneCount / TEST_MAX_ZONE_THREADS;
sl@0: 		}
sl@0: 
sl@0: 	while (1)
sl@0: 		{
sl@0: 		TInt index = 0;
sl@0: 		TInt tempy = 0;
sl@0: 		for (; index < numZones; index ++)
sl@0: 			{
sl@0: 			User::AfterHighRes(TEST_MAX_ZONE_THREADS*TickPeriod/4);
sl@0: 			tempy = zoneId + (TEST_MAX_ZONE_THREADS * index);
sl@0: 			if (tempy < (TInt)TestZoneCount)
sl@0: 				{
sl@0: 				RamstressLdd.DoMovePagesInZone(tempy);
sl@0: 				}
sl@0: 			if (TestDefragTestEnd)
sl@0: 				break;
sl@0: 			}
sl@0: 		if (TestDefragTestEnd)
sl@0: 			break;
sl@0: 		}	
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoDefragAutoTest
sl@0: //
sl@0: // Call the auto tests whilst defraging in the background.
sl@0: //
sl@0: 
sl@0: void DoDefragAutoTest()
sl@0: 	{
sl@0: 	TUint	localZoneCount = TestZoneCount;
sl@0: 	if (TestZoneCount > TEST_MAX_ZONE_THREADS)
sl@0: 		{
sl@0: 		localZoneCount = TEST_MAX_ZONE_THREADS;
sl@0: 		}
sl@0: 	TInt			size =    (sizeof(RThread) * localZoneCount) 
sl@0: 							+ (sizeof(TInt) * localZoneCount);
sl@0: 	TUint8*			pBuf = (TUint8*)User::AllocZ(size);
sl@0: 
sl@0: 	test(pBuf != NULL);
sl@0: 	RThread			*pTheThreads = (RThread*)pBuf;
sl@0: 	TInt			*pThreadInUse = (TInt*)(pTheThreads + localZoneCount);
sl@0: 	TInt			 ret;
sl@0: 	TUint			 index;
sl@0: 	for (index = 0; index < localZoneCount; index ++)
sl@0: 		{
sl@0: 		DBGS_PRINT((_L("%S : Starting Defrag Thread %d\n"), &TestNameBuffer, index));
sl@0: 		ret = pTheThreads[index].Create(KTestBlank,MultipleDefragThread,KDefaultStackSize,NULL,(TAny*) index);
sl@0: 		if (ret == KErrNone)
sl@0: 			{
sl@0: 			pTheThreads[index].Resume();
sl@0: 			pThreadInUse[index] = 1;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("%S : Starting Defrag Thread Failed %d\n"), &TestNameBuffer, index));
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// Do the full auto tests...
sl@0: 	PerformAutoTest(TestIsDemandPaged);
sl@0: 
sl@0: 	TestDefragTestEnd = ETrue;
sl@0: 	RamstressLdd.DoSetEndFlag(1);
sl@0: 	TBool	anyUsed = ETrue;
sl@0: 
sl@0: 	DBGS_PRINT((_L("%S : Waiting for Defrag Threads to exit...\n"), &TestNameBuffer));	
sl@0: 	TUint killNext = User::TickCount();
sl@0: 	while(anyUsed)
sl@0: 		{
sl@0: 		anyUsed = EFalse;
sl@0: 		
sl@0: 		// walk through the thread list to check which are still alive.
sl@0: 		for (index = 0; index < localZoneCount; index++)
sl@0: 			{
sl@0: 			if (pThreadInUse[index])
sl@0: 				{
sl@0: 				if (pTheThreads[index].ExitType() != EExitPending)
sl@0: 					{
sl@0: 					if (pTheThreads[index].ExitType() == EExitPanic)
sl@0: 						{
sl@0: 						DBGS_PRINT((_L("%S : Defrag Thread %d Panic'd\n"), &TestNameBuffer, index));	
sl@0: 						}
sl@0: 					else
sl@0: 						{
sl@0: 						DBGS_PRINT((_L("%S : Defrag Thread %d Exited\n"), &TestNameBuffer, index));	
sl@0: 						}
sl@0: 					pTheThreads[index].Close();
sl@0: 					pThreadInUse[index] = EFalse;
sl@0: 					}
sl@0: 				else
sl@0: 					{
sl@0: 					anyUsed = ETrue;
sl@0: 					TUint now = User::TickCount();
sl@0: 					TUint time = TUint((TUint64)(now-killNext)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 					const TUint killTimeStep = (TEST_DOT_PERIOD+9)/10; // 1/10th of a dot
sl@0: 					if(time>TEST_DOT_PERIOD+killTimeStep)
sl@0: 						{
sl@0: 						killNext += killTimeStep*1000000/TickPeriod;
sl@0: 						DBGS_PRINT((_L("%S : killing Defrag Thread %d\n"), &TestNameBuffer, index));	
sl@0: 						pTheThreads[index].Kill(KErrNone);
sl@0: 						pTheThreads[index].Close();
sl@0: 						pThreadInUse[index] = EFalse;
sl@0: 						}
sl@0: 					}
sl@0: 				}
sl@0: 			}
sl@0: 		User::After(500000);
sl@0: 		}
sl@0: 	DBGS_PRINT((_L("%S : Defrag Threads exited...\n"), &TestNameBuffer));	
sl@0: 	RamstressLdd.DoSetEndFlag(0);
sl@0: 	User::Free(pBuf);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoDefragTest
sl@0: //
sl@0: // Test the ram defrag code.
sl@0: //
sl@0: 
sl@0: void DoDefragTest(void)
sl@0: 	{
sl@0: 	SVMCacheInfo  tempPages;
sl@0: 	memset(&tempPages, 0, sizeof(tempPages));
sl@0: 
sl@0: 	test.Next(_L("Ram Defrag : Get the number of zones"));
sl@0: 	// first get the number of zones
sl@0: 	TInt ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneCount,&TestZoneCount,0);
sl@0: 	if(ret==KErrNotSupported)
sl@0: 		{
sl@0: 		test.Next(_L("TESTS NOT RUN - Ram Defrag appears to not be supported.\n"));
sl@0: 		return;
sl@0: 		}
sl@0: 	test(ret == KErrNone);
sl@0: 	test(TestZoneCount != 0);
sl@0: 	test.Printf(_L("RAM Zones (count=%u)\n"),TestZoneCount);
sl@0: 
sl@0: 	// now get the config of each of the zones.
sl@0: 	TUint						index;
sl@0: 	struct SRamZoneConfig		config;
sl@0: 	struct SRamZoneUtilisation	util;
sl@0: 	test.Next(_L("Ram Defrag : Get info about the zones"));
sl@0: 	for (index = 0; index < TestZoneCount; index ++)
sl@0: 		{
sl@0: 		ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneConfig,(TAny*)index, (TAny*)&config);
sl@0: 		test(ret == KErrNone);
sl@0: 		test.Printf(_L("config : id=%d index=%d base=0x%08x end=0x%08x pages=%d pref=%d flags=0x%x\n"),
sl@0: 					config.iZoneId,config.iZoneIndex,config.iPhysBase,config.iPhysEnd,config.iPhysPages, 
sl@0: 					config.iPref,config.iFlags);
sl@0: 
sl@0: 		ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation,(TAny*)index, (TAny*)&util);
sl@0: 		test(ret == KErrNone);
sl@0: 		test.Printf(_L("usage  : id=%d index=%d pages=%d free=%d unknown=%d fixed=%d move=%d discard=%d other=%d\n"),
sl@0: 					util.iZoneId,util.iZoneIndex,util.iPhysPages,util.iFreePages,
sl@0: 					util.iAllocUnknown,util.iAllocFixed,util.iAllocMovable,util.iAllocDiscardable,util.iAllocOther);
sl@0: 		}
sl@0: 	// Now test for zones out of range.
sl@0: 	test.Next(_L("Ram Defrag : test out of range indexes"));
sl@0: 	ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneConfig,(TAny*)(TestZoneCount + 1), (TAny*)&config);
sl@0: 	test(ret != KErrNone);
sl@0: 	ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation,(TAny*)(TestZoneCount + 1), (TAny*)&util);
sl@0: 	test(ret != KErrNone);
sl@0: 
sl@0: 	ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneConfig,(TAny*)-1, (TAny*)&config);
sl@0: 	test(ret != KErrNone);
sl@0: 	ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation,(TAny*)-1, (TAny*)&util);
sl@0: 	test(ret != KErrNone);
sl@0: 	test.Next(_L("Ram Defrag : test out of range enums"));
sl@0: 	ret = UserSvr::HalFunction(EHalGroupRam,-1, 0, 0);
sl@0: 	test(ret != KErrNone);
sl@0: 	ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation + 1,0, 0);
sl@0: 	test(ret != KErrNone);
sl@0: 
sl@0: 	TInt r = User::LoadLogicalDevice(KRamStressTestLddName);
sl@0: 	RUNTEST1(r==KErrNone || r==KErrAlreadyExists);
sl@0: 	RUNTEST(RamstressLdd.Open(),KErrNone);
sl@0: 	//TestDebug = ETrue;
sl@0: 	RUNTEST(RamstressLdd.DoSetDebugFlag((TInt)TestDebug),KErrNone);
sl@0: 
sl@0: 	test.Next(_L("Ram Defrag : set VM cache to stress free..."));
sl@0: 
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		// get the old cache info
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
sl@0: 
sl@0: 		TInt minSize = 512 * 4096;
sl@0: 		TInt maxSize = 32767 * 4096;
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 		}
sl@0: 
sl@0: 	test.Next(_L("Ram Defrag : move all pages in all zone in 1 thread..."));
sl@0: 
sl@0: 	for (index = 0; index < TestZoneCount; index ++)
sl@0: 		{
sl@0: 		test.Printf(_L("Ram Defrag : moving pages in zone %u\n"),index);
sl@0: 		ret = RamstressLdd.DoMovePagesInZone(index);
sl@0: 		if (ret != KErrNone)
sl@0: 			{
sl@0: 			test.Printf(_L("Ram Defrag : moving pages in zone failed %u err=%d\n"), index, ret);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 
sl@0: 	test.Next(_L("Ram Defrag : Get info after test"));
sl@0: 	for (index = 0; index < TestZoneCount; index ++)
sl@0: 		{
sl@0: 		ret = UserSvr::HalFunction(EHalGroupRam,ERamHalGetZoneUtilisation,(TAny*)index, (TAny*)&util);
sl@0: 		test(ret == KErrNone);
sl@0: 		test.Printf(_L("usage  : id=%d index=%d pages=%d free=%d unknown=%d fixed=%d move=%d discard=%d other=%d\n"),
sl@0: 					util.iZoneId,util.iZoneIndex,util.iPhysPages,util.iFreePages,
sl@0: 					util.iAllocUnknown,util.iAllocFixed,util.iAllocMovable,util.iAllocDiscardable,util.iAllocOther);
sl@0: 		}
sl@0: 
sl@0: 	test.Next(_L("Ram Defrag : Page moving on multiple threads with auto test running."));
sl@0: 
sl@0: 	TestingDefrag = ETrue;
sl@0: 	TestDefragTestEnd = EFalse;
sl@0: 
sl@0: 	DoDefragAutoTest();
sl@0: 	TestingDefrag = EFalse;
sl@0: 	/*
sl@0: 	 * End of test cleanup.
sl@0: 	 */
sl@0: 
sl@0: 	test.Next(_L("Ram Defrag : reset VM cache back to stressed."));
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		TInt minSize = tempPages.iMinSize;
sl@0: 		TInt maxSize = tempPages.iMaxSize;
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 		}
sl@0: 	RamstressLdd.Close();
sl@0: 	test.Next(_L("Ram Defrag : Done"));
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // PerformExceptionThread
sl@0: //
sl@0: // Generate a Panic
sl@0: //
sl@0: 
sl@0: LOCAL_C TInt PerformExceptionThread(TAny* )
sl@0: 	{
sl@0: 	User::AfterHighRes(1000000);
sl@0: 	// this line will cause a Kern::Exec 0 !!!
sl@0: 	test.Printf(_L("Hello World\n"));
sl@0: 
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoExceptionInAnotherThread
sl@0: //
sl@0: // Test the d_exc and minkda functionality with faulting processes.
sl@0: //
sl@0: 
sl@0: void DoExceptionInAnotherThread(void)
sl@0: 	{
sl@0: 	TRequestStatus	theStatus;
sl@0: 	RThread			theThread;
sl@0: 	
sl@0: 	TInt ret = theThread.Create(KTestBlank,PerformExceptionThread,KDefaultStackSize,NULL,NULL);
sl@0: 	test(ret == KErrNone);
sl@0: 	theThread.Logon(theStatus);
sl@0: 	RUNTEST1(theStatus == KRequestPending);	
sl@0: 	theThread.Resume();
sl@0: 	theThread.Close();
sl@0: 	User::WaitForRequest(theStatus);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoTestD_Exc
sl@0: //
sl@0: // Test the d_exc and minkda functionality with faulting processes.
sl@0: //
sl@0: 
sl@0: TInt DoTestD_Exc()
sl@0: 	{
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		test.Next(_L("DoTestD_Exc : d_exc check test."));
sl@0: 		}
sl@0: 	DBGS_PRINT((_L("%S : DoTestD_Exc start...\n"), &TestNameBuffer));	
sl@0: 	// first we need to spawn d_exc.exe
sl@0: 	RProcess dexcProcess;
sl@0: 	TInt ret = dexcProcess.Create(_L("d_exc.exe"),_L("-b"));
sl@0: 	RUNTEST1(KErrNone == ret);
sl@0: 	TRequestStatus dexcStatus;
sl@0: 	dexcProcess.Logon(dexcStatus);
sl@0: 	RUNTEST1(dexcStatus == KRequestPending);	
sl@0: 	dexcProcess.Resume();
sl@0: 
sl@0: 	DBGS_PRINT((_L("%S : DoTestD_Exc started d_exc.exe\n"), &TestNameBuffer));	
sl@0: 
sl@0: 	DoExceptionInAnotherThread();
sl@0: 
sl@0: 	DBGS_PRINT((_L("%S : DoTestD_Exc test completed\n"), &TestNameBuffer));	
sl@0: 	// check that d_exc and minkda don't die!
sl@0: 	RUNTEST1(dexcProcess.ExitType() == EExitPending);
sl@0: 
sl@0: 	DBGS_PRINT((_L("%S : DoTestD_Exc d_exc still running\n"), &TestNameBuffer));	
sl@0: 	
sl@0: 	// kill off d_exc!
sl@0: 	dexcProcess.Kill(KErrNone);
sl@0: 	dexcProcess.Close();
sl@0: 	User::WaitForRequest(dexcStatus);
sl@0: 	DBGS_PRINT((_L("%S : DoTestD_Exc d_exc killed and exiting\n"), &TestNameBuffer));	
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: 	Get name of the hash file used for an EXE or DLL which has been
sl@0: 	copied to writable media.
sl@0: 
sl@0: 	@param	aOrigName		Name of EXE or DLL which has been copied to
sl@0: 							writable media.  This does not have to be
sl@0: 							qualified because only the name and extension
sl@0: 							are used.
sl@0: 	@param	aHashName		On return this is set to the absolute filename
sl@0: 							which should contain the file's hash.  This
sl@0: 							function does not create the file, or its containing
sl@0: 							directory.
sl@0:  */
sl@0: 
sl@0: static void GetHashFileName(const TDesC& aOrigName, TDes& aHashName)
sl@0: 	{
sl@0: 	aHashName.Copy(KSysHash);
sl@0: 	aHashName[0] = (TUint8) RFs::GetSystemDriveChar();
sl@0: 	const TParsePtrC ppc(aOrigName);
sl@0: 	aHashName.Append(ppc.NameAndExt());
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // HashFile
sl@0: // take hash of files require full drive:/path/name.ext
sl@0: //
sl@0: 
sl@0: void HashFile(const TDesC& aFileName, RFs& aFs)
sl@0: 	{
sl@0: 	CSHA1* sha1 = CSHA1::NewL();
sl@0: 	CleanupStack::PushL(sha1);
sl@0: 	
sl@0: 	TBuf<50> hashfile;
sl@0: 	hashfile = KSysHash;
sl@0: 	hashfile[0] = (TUint8) RFs::GetSystemDriveChar();
sl@0: 	
sl@0: 	TInt r = aFs.MkDirAll(hashfile);
sl@0: 	RUNTEST1(r==KErrNone || r==KErrAlreadyExists);
sl@0: 
sl@0: 	RFile fDest;
sl@0: 	r = fDest.Open(aFs, aFileName, EFileRead | EFileStream);
sl@0: 	if (r != KErrNone)
sl@0: 		{
sl@0: 		if (TestingReaper && (r == KErrInUse))
sl@0: 			{
sl@0: 			TBool whinged = EFalse;
sl@0: 			while (r == KErrInUse)
sl@0: 				{
sl@0: 				User::After(2000000);
sl@0: 				if (!whinged)
sl@0: 					{
sl@0: 					DBGS_PRINT((_L("HashFile() retrying Open for %S (%d)\n"), &aFileName, r));
sl@0: 					whinged = ETrue;
sl@0: 					}
sl@0: 				r = fDest.Open(aFs, aFileName, EFileRead | EFileStream);
sl@0: 				}
sl@0: 
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("fDest.Open returned %d\n"), r));
sl@0: 			}
sl@0: 		}
sl@0: 	User::LeaveIfError(r);
sl@0: 	CleanupClosePushL(fDest);
sl@0: 
sl@0: 	TBool done;
sl@0: 	TBuf8<512> content;
sl@0: 	do
sl@0: 		{
sl@0: 		r = fDest.Read(content);
sl@0: 		if (r!=KErrNone)
sl@0: 			DBGS_PRINT((_L("fDest.Read returned %d\n"), r));	
sl@0: 		User::LeaveIfError(r);
sl@0: 		done = (content.Length() == 0);
sl@0: 		if (! done)
sl@0: 			sha1->Update(content);
sl@0: 		} while (! done);
sl@0: 	CleanupStack::PopAndDestroy(&fDest);
sl@0: 
sl@0: 	// write hash to \sys\hash
sl@0: 	TBuf8<SHA1_HASH> hashVal = sha1->Final();
sl@0: 
sl@0: 	TFileName fnSrc(aFileName);
sl@0: 	GetHashFileName(aFileName, fnSrc);
sl@0: 	RFile fHash;
sl@0: 	r = fHash.Replace(aFs, fnSrc, EFileWrite | EFileStream);
sl@0: 	if (r != KErrNone)
sl@0: 		DBGS_PRINT((_L("fHash.Replace returned %d\n"), r));
sl@0: 	User::LeaveIfError(r);
sl@0: 	CleanupClosePushL(fHash);
sl@0: 	r = fHash.Write(hashVal);
sl@0: 	if (r != KErrNone)
sl@0: 		DBGS_PRINT((_L("fHash.Write returned %d\n"), r));
sl@0: 	User::LeaveIfError(r);
sl@0: 
sl@0: 	CleanupStack::PopAndDestroy(2, sha1);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // CopyFileToMMc
sl@0: //
sl@0: // Copy a file to the MMC card and create a hash of it.
sl@0: //
sl@0: 
sl@0: TInt CopyFileToMMc(RFs& aFs,CFileMan* aFileMan, TPtrC aPath, TPtrC  aOldFilename, TPtrC  aNewFilename)
sl@0: 	{
sl@0: 	TInt retVal = aFs.MkDirAll(aPath);
sl@0: 	RUNTEST1(retVal==KErrNone || retVal==KErrAlreadyExists);
sl@0: 
sl@0: 	TFileName newPath;
sl@0: 	TFileName oldPath;
sl@0: 
sl@0: 	oldPath.Format(_L("%S%S"),&KRomPath, &aOldFilename);
sl@0: 	newPath.Format(_L("%S%S"),&aPath, &aNewFilename);
sl@0: 	DBGD_PRINT((_L("Copying %S to %S\n"), &oldPath, &newPath));
sl@0: 	retVal = aFileMan->Copy(oldPath, newPath, CFileMan::EOverWrite);
sl@0: 	if (retVal == KErrNone)
sl@0: 		{
sl@0: 		retVal = aFileMan->Attribs(newPath, KEntryAttNormal, KEntryAttReadOnly, 0);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("%S :   Attribs failed (%d)\n"), &newPath, retVal));
sl@0: 			}
sl@0: 		TEntry  anEntry;
sl@0: 		retVal = aFs.Entry(newPath, anEntry);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("%S : aFs.Entry failed (%d)\n"), &newPath, retVal));
sl@0: 			}
sl@0: 		TRAPD(r, HashFile(newPath, aFs));
sl@0: 		RUNTEST1(r == KErrNone);
sl@0: 		}
sl@0: 	else
sl@0: 		DBGS_PRINT((_L("Failed to copy file %d\n"), retVal));
sl@0: 	DBGD_PRINT((_L("%S : now %S (%d)\n"), &newPath, EXISTS(retVal), retVal));
sl@0: 	return retVal;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // CopyAndFragmentFiles
sl@0: //
sl@0: // Copy the test files to a specified location edeavouring to fragment as much as possible.
sl@0: //
sl@0: 
sl@0: TBool CopyAndFragmentFiles(RFs& aFs,CFileMan* aFileMan, TPtrC aPath, ETestMediaType aMediaType)
sl@0: 	{
sl@0: 	TInt retVal = aFs.MkDirAll(aPath);
sl@0: 	RUNTEST1(retVal==KErrNone || retVal==KErrAlreadyExists);
sl@0: #define FILECOUNTMAX (PAGELDRTST_MAX_DLLS + 2)
sl@0: 	RFile	theInFiles[FILECOUNTMAX];
sl@0: 	RFile	theOutFiles[FILECOUNTMAX];
sl@0: 	TInt	inFileSize[FILECOUNTMAX];
sl@0: 	TInt	inFilePos[FILECOUNTMAX];
sl@0: 	TBool	fileOk[FILECOUNTMAX];
sl@0: 
sl@0: 	TInt	  index;
sl@0: 	TFileName newPath;
sl@0: 	TFileName oldPath;
sl@0: 
sl@0: 	for (index = 0; index < FILECOUNTMAX; index ++)
sl@0: 		{
sl@0: 		inFileSize[index] = 0;
sl@0: 		inFilePos[index] = 0;
sl@0: 		fileOk[index] = EFalse;
sl@0: 
sl@0: 		if (index < PAGELDRTST_MAX_DLLS)
sl@0: 			{
sl@0: 			oldPath.Format(_L("%S%S%d%S"), &KRomPath, &KDllBaseName, index, &TestPlExtNames[KTestMediaBase]);
sl@0: 			newPath.Format(_L("%S%S%d%S"), &aPath, &KDllBaseName, index, &TestPlExtNames[aMediaType]);
sl@0: 			}
sl@0: 		else if (index < (PAGELDRTST_MAX_DLLS + 1))
sl@0: 			{
sl@0: 			oldPath.Format(_L("%S%S"), &KRomPath, &TestPsExeNames[KTestMediaBase]);
sl@0: 			newPath.Format(_L("%S%S"), &aPath, &TestPsExeNames[aMediaType]);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			oldPath.Format(_L("%S%S"), &KRomPath, &TestPlExeNames[KTestMediaBase]);
sl@0: 			newPath.Format(_L("%S%S"), &aPath, &TestPlExeNames[aMediaType]);
sl@0: 			}
sl@0: 
sl@0: 		retVal = theInFiles[index].Open(aFs, oldPath, EFileRead);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("%S : Failed to open for read (%d)\n"), &oldPath, retVal));
sl@0: 			break;
sl@0: 			}
sl@0: 		retVal = theInFiles[index].Size(inFileSize[index]);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			theInFiles[index].Close();
sl@0: 			DBGS_PRINT((_L("%S : Failed to get file size (%d)\n"), &newPath, retVal));
sl@0: 			break;
sl@0: 			}
sl@0: 		retVal = theOutFiles[index].Replace(aFs, newPath, EFileWrite);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			theInFiles[index].Close();
sl@0: 			DBGS_PRINT((_L("%S : Failed to open for write (%d)\n"), &newPath, retVal));
sl@0: 			break;
sl@0: 			}
sl@0: 
sl@0: 		fileOk[index] = ETrue;
sl@0: 		}
sl@0: 
sl@0: 	const TInt KBufferSize = 3333;
sl@0: 	TBuf8<KBufferSize> buffer;
sl@0: 	TBool stillGoing;
sl@0: 
sl@0: 	do
sl@0: 		{
sl@0: 		stillGoing = EFalse;
sl@0: 		for (index = 0; index < FILECOUNTMAX; index ++)
sl@0: 			{
sl@0: 			if (!fileOk[index])
sl@0: 				break;
sl@0: 			if (inFilePos[index] < inFileSize[index])
sl@0: 				{
sl@0: 				retVal = theInFiles[index].Read(buffer);
sl@0: 				if (retVal != KErrNone)
sl@0: 					{
sl@0: 					DBGS_PRINT((_L("theInFiles[%d] read failed (%d)\n"), index, retVal));
sl@0: 					break;
sl@0: 					}
sl@0: 				retVal = theOutFiles[index].Write(buffer);
sl@0: 				if (retVal != KErrNone)
sl@0: 					{
sl@0: 					DBGS_PRINT((_L("theOutFiles[%d] Write failed (%d)\n"), index, retVal));
sl@0: 					break;
sl@0: 					}
sl@0: 				retVal = theOutFiles[index].Flush();
sl@0: 				if (retVal != KErrNone)
sl@0: 					{
sl@0: 					DBGS_PRINT((_L("theOutFiles[%d] flush failed (%d)\n"), index, retVal));
sl@0: 					break;
sl@0: 					}
sl@0: 				inFilePos[index] += buffer.Length();
sl@0: 				if (inFilePos[index] < inFileSize[index])
sl@0: 					stillGoing = ETrue;
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	while (stillGoing);
sl@0: 
sl@0: 	TBool allOk = retVal == KErrNone;
sl@0: 	for (index = 0; index < FILECOUNTMAX; index ++)
sl@0: 		{
sl@0: 		if (!fileOk[index])
sl@0: 			{
sl@0: 			allOk = EFalse;
sl@0: 			break;
sl@0: 			}
sl@0: 		theInFiles[index].Close();
sl@0: 		theOutFiles[index].Close();
sl@0: 		if (index < PAGELDRTST_MAX_DLLS)
sl@0: 			{
sl@0: 			newPath.Format(_L("%S%S%d%S"), &aPath, &KDllBaseName, index, &TestPlExtNames[aMediaType]);
sl@0: 			}
sl@0: 		else if (index < (PAGELDRTST_MAX_DLLS + 1))
sl@0: 			{
sl@0: 			newPath.Format(_L("%S%S"), &aPath, &TestPsExeNames[aMediaType]);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			newPath.Format(_L("%S%S"), &aPath, &TestPlExeNames[aMediaType]);
sl@0: 			}
sl@0: 
sl@0: 		retVal = aFileMan->Attribs(newPath, KEntryAttNormal, KEntryAttReadOnly, 0);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("%S : Attribs failed (%d)\n"), &newPath, retVal));
sl@0: 			allOk = EFalse;
sl@0: 			}
sl@0: 		TEntry  anEntry;
sl@0: 		retVal = aFs.Entry(newPath, anEntry);
sl@0: 		if (retVal != KErrNone)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("%S : aFs.Entry failed (%d)\n"), &newPath, retVal));
sl@0: 			allOk = EFalse;
sl@0: 			}
sl@0: 		TRAPD(r, HashFile(newPath, aFs));
sl@0: 		if (r != KErrNone)
sl@0: 			{
sl@0: 			allOk = EFalse;
sl@0: 			}
sl@0: 		DBGD_PRINT((_L("%S : %S!\n"), &newPath, EXISTS(!allOk)));
sl@0: 		}
sl@0: 	return allOk;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // CheckFilePresence
sl@0: //
sl@0: // Checks all the files required for the test are present and copies some tests to the MMC card
sl@0: //
sl@0: 
sl@0: void CheckFilePresence(TBool aDoFileCopy)
sl@0: 	{
sl@0: 	TUint start = User::TickCount();
sl@0: 
sl@0: 	RFs fs;
sl@0: 	if (KErrNone != fs.Connect())
sl@0: 		{
sl@0: 		DBGS_PRINT(_L("CheckFilePresence : Can't connect to the FS\n"));
sl@0: 		return ;
sl@0: 		}
sl@0: 
sl@0: 	TFileName filename;
sl@0: 	TFileName newFilename;
sl@0: 	TEntry anEntry;
sl@0: 	TInt   index;
sl@0: 	TInt   retVal;
sl@0: 	TInt   dllIndex;
sl@0: 
sl@0: 	// now we need to add the MMC files
sl@0: 	TInt drvNum = FindMMCDriveNumber(fs);
sl@0: 	TBuf<32>	mmcPath;
sl@0: 	mmcPath.Format(_L("%S"),&KMmcDefaultPath);
sl@0: 	if (drvNum >= 0)
sl@0: 		mmcPath[0] = 'a' + drvNum;
sl@0: 
sl@0: 	TBool	allOk;
sl@0: 	//TInt  indexMax = aDoFileCopy ? KTestMediaMmc : KTestMediaCOUNT; 
sl@0: 	for (index = 0; index < TEST_MEDIA_COUNT_HACK; index ++)
sl@0: 		{
sl@0: 		allOk = ETrue;	
sl@0: 		filename.Format(_L("%S%S"),(index == KTestMediaMmc) ? & mmcPath : &KRomPath, &TestPsExeNames[index]);
sl@0: 		if (KErrNone != fs.Entry(filename, anEntry))
sl@0: 			allOk = EFalse;
sl@0: 
sl@0: 		filename.Format(_L("%S%S"),(index == KTestMediaMmc) ? & mmcPath : &KRomPath, &TestPlExeNames[index]);
sl@0: 		if (KErrNone != fs.Entry(filename, anEntry))
sl@0: 			allOk = EFalse;
sl@0: 
sl@0: 		for (dllIndex = 0; dllIndex < PAGELDRTST_MAX_DLLS; dllIndex ++)
sl@0: 			{
sl@0: 			filename.Format(_L("%S%S%d%S"), (index == KTestMediaMmc) ? & mmcPath : &KRomPath, &KDllBaseName, dllIndex, &TestPlExtNames[index]);
sl@0: 			if (KErrNone != fs.Entry(filename, anEntry))
sl@0: 				allOk = EFalse;
sl@0: 			}
sl@0: 		TestDllExesExist[index] = allOk;
sl@0: 		DBGS_PRINT((_L("%S : %S!\n"), &TestPsExeNames[index], EXISTS(!TestDllExesExist[index])));
sl@0: 		}
sl@0: 	TInt nandDrvNum = FindFsNANDDrive(fs);
sl@0: 	if (aDoFileCopy && (drvNum >= 0) && (nandDrvNum >= 0))
sl@0: 		{
sl@0: 		CTrapCleanup* cleanupStack = CTrapCleanup::New();
sl@0: 		if(!cleanupStack)
sl@0: 			DBGS_PRINT((_L("Cleanup stack failed\n")));	
sl@0: 		CFileMan* pFileMan = NULL;
sl@0: 		TRAP(retVal, pFileMan = CFileMan::NewL(fs));
sl@0: 	
sl@0: 		// First make a clean copy of the DLLs to the MMC card.
sl@0: 		allOk = ETrue;			
sl@0: 		if (KErrNone != CopyFileToMMc(fs, pFileMan, mmcPath, TestPsExeNames[KTestMediaBase], TestPsExeNames[KTestMediaMmc]))
sl@0: 			allOk = EFalse;
sl@0: 		if (KErrNone != CopyFileToMMc(fs, pFileMan, mmcPath, TestPlExeNames[KTestMediaBase], TestPlExeNames[KTestMediaMmc]))
sl@0: 			allOk = EFalse;
sl@0: 		for (dllIndex = 0; dllIndex < PAGELDRTST_MAX_DLLS; dllIndex ++)
sl@0: 			{
sl@0: 			filename.Format(_L("%S%d%S"), &KDllBaseName, dllIndex, &TestPlExtNames[KTestMediaBase]);
sl@0: 			newFilename.Format(_L("%S%d%S"), &KDllBaseName, dllIndex, &TestPlExtNames[KTestMediaMmc]);
sl@0: 			if (KErrNone != CopyFileToMMc(fs, pFileMan, mmcPath, filename, newFilename))
sl@0: 				allOk = EFalse;
sl@0: 			}
sl@0: 		TestDllExesExist[KTestMediaMmc] = allOk;
sl@0: 		DBGS_PRINT((_L("%S : %S! (Drive %c)\n"), &TestPsExeNames[index], EXISTS(!TestDllExesExist[index]), mmcPath[0]));
sl@0: #ifdef TEST_ADD_FRAGD_MEDIA
sl@0: 		//now make some fragmented files on the MMC card.
sl@0: 		TestDllExesExist[KTestMediaMmcFrag] = CopyAndFragmentFiles(fs, pFileMan, mmcPath, KTestMediaMmcFrag);
sl@0: 		DBGS_PRINT((_L("%S : %S! (Drive %c)\n"), &TestPsExeNames[KTestMediaMmcFrag], EXISTS(!TestDllExesExist[KTestMediaMmcFrag]), mmcPath[0]));
sl@0: 
sl@0: 		//now make some fragmented files on the NAND card.
sl@0: 		if (nandDrvNum >= 0)
sl@0: 			{
sl@0: 			mmcPath[0] = 'a' + nandDrvNum;
sl@0: 			TestDllExesExist[KTestMediaNandFrag] = CopyAndFragmentFiles(fs, pFileMan, mmcPath, KTestMediaNandFrag);
sl@0: 			DBGS_PRINT((_L("%S : %S! (Drive %c)\n"), &TestPsExeNames[KTestMediaNandFrag], EXISTS(!TestDllExesExist[KTestMediaNandFrag]), mmcPath[0]));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("CheckFilePresence : Failed to get NAND drive number\n")));
sl@0: #endif // TEST_ADD_FRAGD_MEDIA
sl@0: 		delete pFileMan; pFileMan = NULL;
sl@0: 		delete cleanupStack; cleanupStack = NULL;
sl@0: 		}
sl@0: 
sl@0: 	fs.Close();
sl@0: 
sl@0: 	TUint end = User::TickCount();
sl@0: 	TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 	DBGS_PRINT((_L("CheckFilePresence : %d secs elapsed\n"), time));
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DoDeleteFile
sl@0: //
sl@0: // Delete a file and remove the hash
sl@0: //
sl@0: 
sl@0: void DoDeleteFile(CFileMan* aFileMan, TBool aSilent,TFileName& aFileName )
sl@0: 	{
sl@0: 	TFileName hashName;
sl@0: 	RLoader l;
sl@0: 	test(l.Connect() == KErrNone);
sl@0: 
sl@0: 	DBGD_PRINT((_L("Deleting %S ...\n"), &aFileName));
sl@0: 	if (!aSilent)
sl@0: 		DBGD_PRINT((_L("Deleting %S\n"), &aFileName));
sl@0: 	TInt retVal = aFileMan->Delete(aFileName);
sl@0: 	if (retVal != KErrNone)
sl@0: 		{
sl@0: 		if (TestingReaper)
sl@0: 			{
sl@0: 			aFileMan->Attribs(aFileName, KEntryAttNormal, KEntryAttReadOnly, 0);
sl@0: 			retVal = l.Delete(aFileName);
sl@0: 			if (retVal != KErrNone)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("RLoader::Delete %S Failed %d\n"), &aFileName, retVal));
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			if (!aSilent)
sl@0: 				DBGS_PRINT((_L("Deleting %S Failed %d\n"), &aFileName, retVal));
sl@0: 			}
sl@0: 		}
sl@0: 	GetHashFileName(aFileName, hashName);
sl@0: 	retVal = aFileMan->Delete(hashName);
sl@0: 	if (retVal != KErrNone)
sl@0: 		{
sl@0: 		if (TestingReaper && (retVal == KErrInUse))
sl@0: 			{
sl@0: 			retVal = l.Delete(hashName);
sl@0: 			if (retVal != KErrNone)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("RLoader::Delete %S Failed %d\n"), &hashName, retVal));
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			if (!aSilent)
sl@0: 				DBGS_PRINT((_L("Deleting %S Failed %d\n"), &hashName, retVal));
sl@0: 			}
sl@0: 		}
sl@0: 	l.Close();
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // CleanupFiles
sl@0: //
sl@0: // Remove any copied files and created directories.
sl@0: //
sl@0: 
sl@0: void CleanupFiles(TBool silent)
sl@0: 	{
sl@0: 	TUint start = User::TickCount();
sl@0: 
sl@0: 	RFs fs;
sl@0: 	if (KErrNone != fs.Connect())
sl@0: 		{
sl@0: 		DBGS_PRINT(_L("CleanupFiles : Can't connect to the FS\n"));
sl@0: 		return ;
sl@0: 		}
sl@0: 
sl@0: 	CTrapCleanup* cleanupStack = CTrapCleanup::New();
sl@0: 	if(!cleanupStack)
sl@0: 		if (!silent)
sl@0: 			DBGS_PRINT((_L("Cleanup stack failed\n")));	
sl@0: 	
sl@0: 	CFileMan* pFileMan = NULL;
sl@0: 	TInt retVal;
sl@0: 	TRAP(retVal, pFileMan = CFileMan::NewL(fs));
sl@0: 	
sl@0: 	TFileName newPath;
sl@0: 	TInt index;
sl@0: 	TInt dllIndex;
sl@0: 
sl@0: 	TBuf<32>	path;
sl@0: 	path.Format(_L("%S"),&KMmcDefaultPath);
sl@0: 	TInt mmcDrvNum = FindMMCDriveNumber(fs);
sl@0: 	TInt nandDrvNum = FindFsNANDDrive(fs);
sl@0: 	for (index = KTestMediaMmc; index < KTestMediaCOUNT; index ++)
sl@0: 		{
sl@0: #ifdef TEST_ADD_FRAGD_MEDIA
sl@0: 		if (index == KTestMediaNandFrag)
sl@0: 			{
sl@0: 			if (nandDrvNum < 0)
sl@0: 				continue;
sl@0: 			path[0] = 'a' + nandDrvNum;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			if (mmcDrvNum < 0)
sl@0: 				continue;
sl@0: 			path[0] = 'a' + mmcDrvNum;
sl@0: 			}
sl@0: #else
sl@0: 		path[0] = 'a' + mmcDrvNum;
sl@0: #endif
sl@0: 		newPath.Format(_L("%S%S"),&path, &TestPsExeNames[index]);
sl@0: 		DoDeleteFile(pFileMan, silent,  newPath);
sl@0: 
sl@0: 		newPath.Format(_L("%S%S"),&path, &TestPlExeNames[index]);
sl@0: 		DoDeleteFile(pFileMan, silent,  newPath);
sl@0: 		
sl@0: 		for (dllIndex = 0; dllIndex < PAGELDRTST_MAX_DLLS; dllIndex ++)
sl@0: 			{
sl@0: 			newPath.Format(_L("%S%S%d%S"), &path, &KDllBaseName, dllIndex, &TestPlExtNames[index]);
sl@0: 			DoDeleteFile(pFileMan, silent,  newPath);
sl@0: 			}
sl@0: 		}
sl@0: 	if (nandDrvNum >= 0)
sl@0: 		{
sl@0: 		path[0] = 'a' + nandDrvNum;
sl@0: 		fs.RmDir(path);
sl@0: 		}
sl@0: 	if (mmcDrvNum >= 0)
sl@0: 		{
sl@0: 		path[0] = 'a' + mmcDrvNum;
sl@0: 		fs.RmDir(path);
sl@0: 		}
sl@0: 
sl@0: 	delete pFileMan; pFileMan = NULL;
sl@0: 	delete cleanupStack; cleanupStack = NULL;
sl@0: 	fs.Close();
sl@0: 	TUint end = User::TickCount();
sl@0: 	TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 	DBGS_PRINT((_L("CleanupFiles : %d secs elapsed\n"), time));
sl@0: 	}
sl@0: 
sl@0: #ifdef _DEBUG
sl@0: 
sl@0: //
sl@0: // FindLocalDriveNumber
sl@0: //
sl@0: // Find the local drive
sl@0: //
sl@0: 
sl@0: TInt FindLocalDriveNumber(RFs &aFs, TInt aFsDrvNum)
sl@0: 	{
sl@0: 	RFile file;
sl@0: 	TBuf<256> fileName;	
sl@0: 	fileName.Append((TChar)('A' + aFsDrvNum));
sl@0: 	fileName+=_L(":\\f32-tst\\");
sl@0: 	TInt r=aFs.MkDirAll(fileName);
sl@0: 	TInt locDriveNumber = -1;
sl@0: 	if (r==KErrNone || r== KErrAlreadyExists)
sl@0: 		{
sl@0: 		fileName += _L("tempy.txt");
sl@0: 		r=file.Replace(aFs,fileName,EFileWrite);
sl@0: 		if (r!=KErrNone)
sl@0: 			DBGS_PRINT((_L("FindLocalDriveNumber : Error %d: file '%S' could not be created\n"),r,&fileName));
sl@0: 		RUNTEST1(r==KErrNone);
sl@0: 		r=file.Write(_L8("Flies as big as sparrows indoletly buzzing in the warm air, heavy with the stench of rotting carcasses"));
sl@0: 		if (r!=KErrNone)
sl@0: 			{
sl@0: 			DBGS_PRINT((_L("FindLocalDriveNumber : Error %d: could not write to file %d (%S)\n"),r,aFsDrvNum, &fileName));
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			// write caching may be enabled to flush the cache...
sl@0: 			TRequestStatus flushStatus;
sl@0: 			file.Flush(flushStatus);
sl@0: 			User::WaitForRequest(flushStatus);
sl@0: 			// get the block map
sl@0: 			SBlockMapInfo info;
sl@0: 			TInt64 start=0;
sl@0: 			r=file.BlockMap(info, start, -1,ETestDebug);
sl@0: 			if (r==KErrNone || r==KErrCompletion)
sl@0: 				{
sl@0: 				locDriveNumber=info.iLocalDriveNumber;
sl@0: 				DBGD_PRINT((_L("FindLocalDriveNumber : locDriveNumber  %d\n"), locDriveNumber));
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("FindLocalDriveNumber : Error %d: error getting blockmap for drive %d (%S)\n"),r,aFsDrvNum, &fileName));
sl@0: 			}
sl@0: 		aFs.Delete(fileName);
sl@0: 		file.Close();
sl@0: 		}
sl@0: 	else
sl@0: 		DBGS_PRINT((_L("FindLocalDriveNumber : Error %d: error creating dir	\n"),r));
sl@0: 	return locDriveNumber;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // ResetConcurrencyStats
sl@0: //
sl@0: // Reset the stats
sl@0: //
sl@0: 
sl@0: void ResetConcurrencyStats(RFs& aFs)
sl@0: 	{
sl@0: 	if(TestBootedFromMmc)
sl@0: 		{
sl@0: 		TInt fsDriveNum = FindMMCDriveNumber(aFs);
sl@0: 		if (fsDriveNum >= 0)
sl@0: 			{
sl@0: 			TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
sl@0: 			if (locDriveNumber >= 0)
sl@0: 				{
sl@0: 				RUNTEST(PagingInfo::ResetConcurrency(locDriveNumber,EMediaPagingStatsRomAndCode),KErrNone);
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("ResetConcurrencyStats MMC : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("ResetConcurrencyStats MMC : Failed to get fsDriveNum %d\n"), fsDriveNum));
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TInt fsDriveNum = FindFsNANDDrive(aFs);
sl@0: 		if (fsDriveNum >= 0)
sl@0: 			{
sl@0: 			TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
sl@0: 			if (locDriveNumber >= 0)
sl@0: 				{
sl@0: 				RUNTEST(PagingInfo::ResetConcurrency(locDriveNumber,EMediaPagingStatsRomAndCode),KErrNone);
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("ResetConcurrencyStats NAND : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("ResetConcurrencyStats NAND : Failed to get fsDriveNum %d\n"), fsDriveNum));
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // ResetBenchmarks
sl@0: //
sl@0: // Reset the stats
sl@0: //
sl@0: 
sl@0: void ResetBenchmarks(RFs& aFs)
sl@0: 	{
sl@0: 	if(TestBootedFromMmc)
sl@0: 		{
sl@0: 		TInt fsDriveNum = FindMMCDriveNumber(aFs);
sl@0: 		if (fsDriveNum >= 0)
sl@0: 			{
sl@0: 			TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
sl@0: 			if (locDriveNumber >= 0)
sl@0: 				{
sl@0: 				RUNTEST(PagingInfo::ResetBenchmarks(locDriveNumber,EMediaPagingStatsRomAndCode),KErrNone);
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("ResetBenchmarks MMC : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("ResetBenchmarks MMC : Failed to get fsDriveNum %d\n"), fsDriveNum));
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TInt fsDriveNum = FindFsNANDDrive(aFs);
sl@0: 		if (fsDriveNum >= 0)
sl@0: 			{
sl@0: 			TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
sl@0: 			if (locDriveNumber >= 0)
sl@0: 				{
sl@0: 				RUNTEST(PagingInfo::ResetBenchmarks(locDriveNumber,EMediaPagingStatsRomAndCode),KErrNone);
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("ResetBenchmarks NAND : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("ResetBenchmarks NAND : Failed to get fsDriveNum %d\n"), fsDriveNum));
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // DisplayConcurrencyStats
sl@0: //
sl@0: // Display the stats
sl@0: //
sl@0: 
sl@0: void DisplayConcurrencyStats(RFs& aFs)
sl@0: 	{
sl@0: 	if(TestBootedFromMmc)
sl@0: 		{
sl@0: 		TInt fsDriveNum = FindMMCDriveNumber(aFs);
sl@0: 		if (fsDriveNum >= 0)
sl@0: 			{
sl@0: 			TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
sl@0: 			if (locDriveNumber >= 0)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("MMC stats\n")));
sl@0: 				RUNTEST1(PagingInfo::PrintConcurrency(locDriveNumber,EMediaPagingStatsRomAndCode)==KErrNone);
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("DisplayConcurrencyStats MMC : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("DisplayConcurrencyStats MMC : Failed to get fsDriveNum %d\n"), fsDriveNum));
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TInt fsDriveNum = FindFsNANDDrive(aFs);
sl@0: 		if (fsDriveNum >= 0)
sl@0: 			{
sl@0: 			TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
sl@0: 
sl@0: 			if (locDriveNumber >= 0)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("NAND stats\n")));
sl@0: 				RUNTEST1(PagingInfo::PrintConcurrency(locDriveNumber,EMediaPagingStatsRomAndCode)==KErrNone);
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("DisplayConcurrencyStats NAND : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("DisplayConcurrencyStats NAND : Failed to get fsDriveNum %d\n"), fsDriveNum));
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void DisplayBenchmarks(RFs& aFs)
sl@0: 	{
sl@0: 	if(TestBootedFromMmc)
sl@0: 		{
sl@0: 		TInt fsDriveNum = FindMMCDriveNumber(aFs);
sl@0: 		if (fsDriveNum >= 0)
sl@0: 			{
sl@0: 			TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
sl@0: 			if(locDriveNumber>=0)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("MMC benchmarks\n")));
sl@0: 				RUNTEST1(PagingInfo::PrintBenchmarks(locDriveNumber,EMediaPagingStatsRomAndCode)==KErrNone);
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("DisplayBenchmarks MMC : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("DisplayBenchmarks MMC : Failed to get fsDriveNum %d\n"), fsDriveNum));
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TInt fsDriveNum = FindFsNANDDrive(aFs);
sl@0: 		if (fsDriveNum >= 0)
sl@0: 			{
sl@0: 			TInt locDriveNumber = FindLocalDriveNumber(aFs, fsDriveNum);
sl@0: 			if(locDriveNumber>=0)
sl@0: 				{
sl@0: 				DBGS_PRINT((_L("NAND benchmarks\n")));
sl@0: 				RUNTEST1(PagingInfo::PrintBenchmarks(locDriveNumber,EMediaPagingStatsRomAndCode)==KErrNone);
sl@0: 				}
sl@0: 			else
sl@0: 				DBGS_PRINT((_L("DisplayBenchmarks NAND : Failed to get locDriveNumber %d (%d)\n"), locDriveNumber, fsDriveNum));
sl@0: 			}
sl@0: 		else
sl@0: 			DBGS_PRINT((_L("DisplayBenchmarks NAND : Failed to get fsDriveNum %d\n"), fsDriveNum));
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: #endif
sl@0: 
sl@0: void DoStats()
sl@0: 	{
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		SVMCacheInfo  tempPages;
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
sl@0: 		DBGS_PRINT((_L("DPC : min %d max %d curr %d\n"), 
sl@0: 					tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize));
sl@0: 		DBGS_PRINT((_L("    : maxFree %d freeRam %d\n"),
sl@0: 					tempPages.iMaxFreeSize, FreeRam()));
sl@0: 		}
sl@0: 
sl@0: #ifdef _DEBUG
sl@0: 	if (TestWeAreTheTestBase && !TestSilent)
sl@0: 		{
sl@0: 		RFs fs;
sl@0: 		if (KErrNone != fs.Connect())
sl@0: 			{
sl@0: 			DBGS_PRINT(_L("ResetConcurrencyStats : Can't connect to the FS\n"));
sl@0: 			return;
sl@0: 			}
sl@0: 
sl@0: #ifndef TEST_MINIMAL_STATS
sl@0: 		DisplayConcurrencyStats(fs);
sl@0: 		DisplayBenchmarks(fs);
sl@0: #endif
sl@0: #ifndef TEST_DONT_RESET_STATS
sl@0: 		ResetConcurrencyStats(fs);
sl@0: 		ResetBenchmarks(fs);
sl@0: #endif
sl@0: 		fs.Close();
sl@0: 		}
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // E32Main
sl@0: //
sl@0: // Main entry point.
sl@0: //
sl@0: 
sl@0: TInt E32Main()
sl@0: 	{
sl@0: #ifndef TEST_ON_UNPAGED
sl@0: 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
sl@0: 	if(!romHeader->iPageableRomStart)
sl@0: 		{
sl@0: 		TestIsDemandPaged = EFalse;
sl@0: 		}
sl@0: #endif
sl@0: 	// Turn off lazy dll unloading
sl@0: 	RLoader l;
sl@0: 	if (l.Connect() == KErrNone)
sl@0: 		{
sl@0: 		l.CancelLazyDllUnload();
sl@0: 		l.Close();
sl@0: 		}
sl@0: 	
sl@0: 	HAL::Get(HAL::ESystemTickPeriod, TickPeriod);
sl@0: 
sl@0: 	SVMCacheInfo  tempPages;
sl@0: 	memset(&tempPages, 0, sizeof(tempPages));
sl@0: 
sl@0: 	TBool parseResult = ParseCommandLine();
sl@0: 
sl@0: 	if (TestExit)
sl@0: 		{
sl@0: 		return KErrNone;
sl@0: 		}
sl@0: 
sl@0: 	TUint start = User::TickCount();
sl@0: 	
sl@0: 	AreWeTheTestBase();	
sl@0: 
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		TInt  minSize = TestMinCacheSize;
sl@0: 		TInt  maxSize = TestMaxCacheSize;
sl@0: 
sl@0: 		SVMCacheInfo  tempPages;
sl@0: 
sl@0: 		// get the old cache info
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
sl@0: 		// set the cache to our test value
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 		}
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		test.Title();
sl@0: 		test.Start(_L("Demand Paging loader stress tests..."));
sl@0: 		test.Printf(_L("%S (%d)\n"), &TestNameBuffer, TestWeAreTheTestBase);
sl@0: 		test.Printf(_L("TestBootedFromMmc %d\n"), TestBootedFromMmc);
sl@0: 
sl@0: 		if (TestWeAreTheTestBase)
sl@0: 			CleanupFiles(ETrue);
sl@0: 
sl@0: 		CheckFilePresence(TestWeAreTheTestBase);
sl@0: 		}
sl@0: 
sl@0: 	if (parseResult)
sl@0: 		{
sl@0: 		if (TestLowMem)
sl@0: 			{
sl@0: 			DoLowMemTest(ETrue);
sl@0: 			}
sl@0: 		if (TestSingle)
sl@0: 			{
sl@0: 			RUNTEST(DoSingleTest(),KErrNone);
sl@0: 			}
sl@0: 		if (TestMultiple)
sl@0: 			{
sl@0: 			RUNTEST(DoMultipleTest(),KErrNone);
sl@0: 			}
sl@0: 		if (TestD_Exc)
sl@0: 			{
sl@0: 			RUNTEST(DoTestD_Exc(),KErrNone);
sl@0: 			}
sl@0: 		if (TestChunks)
sl@0: 			{
sl@0: 			DoChunkTests();
sl@0: 			}
sl@0: 		if (TestReaper)
sl@0: 			{
sl@0: 			DoReaperTests();
sl@0: 			}
sl@0: 		if (TestBtrace)
sl@0: 			{
sl@0: 			DoBtraceTest();
sl@0: 			}
sl@0: 		if (TestDefrag)
sl@0: 			{
sl@0: 			DoDefragTest();
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: #ifdef _DEBUG
sl@0: 		if (TestWeAreTheTestBase)
sl@0: 			{
sl@0: 			RFs fs;
sl@0: 			if (KErrNone == fs.Connect())
sl@0: 				{
sl@0: 				//fs.SetDebugRegister(KCACHE);
sl@0: 				ResetConcurrencyStats(fs);
sl@0: 				ResetBenchmarks(fs);
sl@0: 				fs.Close();
sl@0: 				}
sl@0: 			}
sl@0: #endif
sl@0: 
sl@0: 		while (1)
sl@0: 			{
sl@0: 			if (TestIsDemandPaged)
sl@0: 				{
sl@0: #ifdef TEST_RUN_AUTOTEST
sl@0: 				PerformAutoTest();
sl@0: #endif //TEST_RUN_AUTOTEST
sl@0: 
sl@0: #ifndef	TEST_SHORT_TEST
sl@0: #ifdef TEST_RUN_LOWMEMTEST
sl@0: 				DoLowMemTest(ETrue);
sl@0: #endif //TEST_RUN_LOWMEMTEST
sl@0: #ifdef TEST_RUN_CHUNKTEST
sl@0: 				DoChunkTests();
sl@0: #endif //TEST_RUN_CHUNKTEST
sl@0: #ifdef TEST_RUN_REAPERTEST
sl@0: 				DoReaperTests();
sl@0: #endif //TEST_RUN_REAPERTEST
sl@0: #endif //TEST_SHORT_TEST
sl@0: 				}
sl@0: 
sl@0: #ifdef TEST_RUN_DEFRAGTEST
sl@0: 			DoDefragTest();
sl@0: #endif //TEST_RUN_DEFRAGTEST
sl@0: 
sl@0: 			if (TestStressFree)
sl@0: 				{
sl@0: 				TInt minSize = 512 * 4096;
sl@0: 				TInt maxSize = 32767 * 4096;
sl@0: 				UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 
sl@0: 				test.Printf(_L("%S Stress Free!!\n"), &TestNameBuffer, TestWeAreTheTestBase);
sl@0: 				TestStressFree = EFalse;
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				break;
sl@0: 				}
sl@0: 			}
sl@0: 
sl@0: #ifndef TEST_SHORT_TEST
sl@0: #ifndef TEST_NO_DEXC_IN_AUTO
sl@0: #ifdef TEST_RUN_D_EXCTEST
sl@0: 		RUNTEST(DoTestD_Exc(),KErrNone);
sl@0: #endif //TEST_RUN_D_EXCTEST
sl@0: #endif //TEST_NO_DEXC_IN_AUTO
sl@0: 		if (TestWeAreTheTestBase && TestFullAutoTest && TestIsDemandPaged)
sl@0: 			{
sl@0: 			RProcess		theProcess;
sl@0: 			TRequestStatus	status;
sl@0: 
sl@0: 			TInt retVal = theProcess.Create(_L("t_pageldrtst_rom.exe"),_L("fullauto"));
sl@0: 			if (retVal != KErrNotFound)
sl@0: 				{
sl@0: 				RUNTEST1(KErrNone == retVal);
sl@0: 				theProcess.Logon(status);
sl@0: 				RUNTEST1(status == KRequestPending);	
sl@0: 				theProcess.Resume();
sl@0: #ifdef TEST_THRASHING_TEST
sl@0: 				while (1)
sl@0: 					{
sl@0: 					if (theProcess.ExitType() != EExitPending)
sl@0: 						{
sl@0: 						RUNTEST1(theProcess.ExitType() != EExitPanic);
sl@0: 						break;
sl@0: 						}
sl@0: 					User::AfterHighRes(1);
sl@0: 					}
sl@0: 				User::WaitForRequest(status);
sl@0: #else
sl@0: 				User::WaitForRequest(status);
sl@0: 				if (theProcess.ExitType() != EExitPending)
sl@0: 					{
sl@0: 					RUNTEST1(theProcess.ExitType() != EExitPanic);
sl@0: 					}
sl@0: #endif //TEST_THRASHING_TEST
sl@0: 				theProcess.Close();
sl@0: 				}
sl@0: 			}
sl@0: #endif //TEST_SHORT_TEST
sl@0: #ifdef _DEBUG
sl@0: 		if (TestWeAreTheTestBase && !TestSilent)
sl@0: 			{
sl@0: 			RFs fs;
sl@0: 			if (KErrNone == fs.Connect())
sl@0: 				{
sl@0: 				DisplayConcurrencyStats(fs);
sl@0: 				DisplayBenchmarks(fs);
sl@0: 				fs.Close();
sl@0: 				}
sl@0: 			}
sl@0: #endif
sl@0: 		}
sl@0: 
sl@0: 	if (TestWeAreTheTestBase && !TestNoClean)
sl@0: 		CleanupFiles(EFalse);
sl@0: 
sl@0: 	if (TestIsDemandPaged)
sl@0: 		{
sl@0: 		TInt minSize = tempPages.iMinSize;
sl@0: 		TInt maxSize = tempPages.iMaxSize;
sl@0: 		// put the cache back to the the original values.
sl@0: 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
sl@0: 		}
sl@0: 	if (!TestSilent)
sl@0: 		{
sl@0: 		TUint end = User::TickCount();
sl@0: 		TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
sl@0: 		test.Printf(_L("%S : Complete (%u seconds)\n"), &TestNameBuffer, time);	
sl@0: 		test.End();
sl@0: 		}
sl@0: 	return KErrNone;
sl@0: 	}