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

// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// @SYMTestCaseID				KBASE-DP_FUNC_ATTRIBUTES-0303
// @SYMTestCaseDesc			Symbian OS Toolchain's Paging Override and the
// Paging Policy settings
// @SYMREQ						REQ6808
// @SYMPREQ					PREQ1110
// @SYMTestPriority			High
// @SYMTestActions
// 1.	Load executables with the RProcess API and run them. Each executable has a
// different set of attributes:
// "	Paging attribute: paged, unpaged or no paging attribute in MMP and/or
// OBY files
// "	Compression mode: specified or not
// "	Executable built in ROM as 'data' or 'file'
// "	Solid binaries or aliases
// Retrieve and analyse the demand paging activity trace caused by the preceding
// action, in order to determine whether this binary is paged on demand or not.
// 2.	Repeat the preceding action by loading DLLs with the RLibrary API and
// making calls to them.
// @SYMTestExpectedResults
// 1.	Process complete without error. If, according to the trace data gathered,
// the main thread newly created process causes the executable to be paged in,
// then it is a proof that the executable is paged. Depending on the Paging
// Override setting and the Loader Paging Policy specified at the time the ROM was
// built, the Loader makes a decision as to whether page the binary or not,
// according to the rules listed in the Design Sketch. This is how we determine
// this, in this order:
// a.	If ROM paging is disabled: not paged
// b.	If executable was built in ROM as 'data': not paged
// c.	If the a file compression scheme was specified at ROM build time: not paged
// d.	If the Loader Paging policy is 'NOT PAGED': not paged
// e.	If the Loader Paging policy is 'ALWAYS PAGE': paged
// f.	If the Paging Override is 'NOT PAGED': not paged
// g.	If the Paging Override is 'ALWAYS PAGE': paged
// h.	If the OBY paging keyword for this executable is 'PAGED': paged
// i.	If the OBY paging keyword for this executable is 'NOT PAGED': unpaged
// j.	If the MMP paging keyword for this executable is 'PAGED': paged
// k.	If the MMP paging keyword for this executable is 'NOT PAGED': not paged
// l.	If the Paging Override is 'DEFAULT UNPAGED': not paged
// m.	If the Paging Override is 'DEFAULT PAGED': paged
// n.	If the Paging Policy is 'DEFAULT UNPAGED': not paged
// o.	The executable must be paged
// 2.	DLL is loaded. Functions are called and complete without errors. The rules
// to determine whether the binary should be paged or not are the same as in the
// preceding action.
// 
//

#include <e32test.h>
#include <e32ldr.h>
#include <d32btrace.h>
#include "u32std.h"
#include <f32file.h>
#include <dptest.h>

#define TEST_EQ(a,b) { if (a != b) { test.Printf(_L("%d != %d\n"), a, b); test(EFalse); } }
#define TEST_CONDITION(a) { if (!a) { test.Printf(_L("TEST FAILED at line %d\n"), __LINE__); pass = EFalse; } }
#define LE4(a) ((TUint) (*((a) + 3) << 24) + (*((a) + 2) << 16) + (*((a) + 1) << 8) + *(a))

RTest test(_L("T_DPATTR"));
RBTrace btrace;
RFs fs;

// ROM paging settings
TBool gIsRomDemangPagingEnabled;
TInt gPagingOverride;
TInt gPagingPolicy;

// This process
TUint32 gNThreadId = 0;

// Test executables attributes flags
enum
	{
	ENone					= 0,
	EMMPPaged				= 1 << 0,		// "PAGED" keyword in MMP file
	EMMPUnpaged				= 1 << 1,		// "UNPAGED" keyword in MMP file
	EMMPCompressTarget		= 1 << 2,		// "COMPRESSTARGET" keyword in MMP file
	EMMPNoCompressTarget	= 1 << 3,		// "UNCOMPRESSTARGET" keyword in MMP file
	EIBYData				= 1 << 4,		// File included as "data" in IBY file
	EIBYFile				= 1 << 5,		// File included as "file" in IBY file
	EIBYFileCompress		= 1 << 6,		// File included as "file_x_" in IBY file (_x_=compression scheme)
	EIBYPaged				= 1 << 7,		// File declared "paged" in IBY file
	EIBYUnpaged				= 1 << 8,		// File declared "unpaged in IBY file
	EIBYAlias				= 1 << 9,		// File name is an alias
	EDLLWritableStaticData	= 1 << 10		// DLL contains writable static data
	};

// Test executables attributes
const TUint testExeAttr[] =
	{
	/* 000 - does not exist */ ENone,
	/* 001 */ EIBYFile,
	/* 002 */ EMMPPaged | EIBYFile,
	/* 003 */ EMMPUnpaged | EIBYFile,
	/* 004 */ EIBYFileCompress,
	/* 005 */ EMMPPaged | EIBYFileCompress,
	/* 006 */ EMMPUnpaged | EIBYFileCompress,
	/* 007 */ EIBYFileCompress,
	/* 008 */ EMMPPaged | EIBYFileCompress,
	/* 009 */ EMMPUnpaged | EIBYFileCompress,
	/* 010 */ EIBYFileCompress,
	/* 011 */ EMMPPaged | EIBYFileCompress,
	/* 012 */ EMMPUnpaged | EIBYFileCompress,
	/* 013 */ EIBYFile | EMMPCompressTarget,
	/* 014 */ EMMPPaged | EIBYFile | EMMPNoCompressTarget,
	/* 015 */ EMMPUnpaged | EIBYFile | EIBYFileCompress | EIBYPaged,
	/* 016 */ EIBYData,
	/* 017 */ EMMPPaged | EIBYData,
	/* 018 */ EMMPUnpaged | EIBYData,
	/* 019 */ EIBYFile | EIBYPaged,
	/* 020 */ EMMPPaged | EIBYFile | EIBYPaged,
	/* 021 */ EMMPUnpaged | EIBYFile | EIBYPaged,
	/* 022 */ EIBYFile | EIBYUnpaged,
	/* 023 */ EMMPPaged | EIBYFile | EIBYUnpaged,
	/* 024 */ EMMPUnpaged | EIBYFile | EIBYUnpaged,
	/* 025 */ EIBYData | EIBYPaged,
	/* 026 */ EMMPPaged | EIBYData | EIBYPaged,
	/* 027 */ EMMPUnpaged | EIBYData | EIBYPaged,
	/* 028 */ EIBYData | EIBYUnpaged,
	/* 029 */ EMMPPaged | EIBYData | EIBYUnpaged,
	/* 030 */ EMMPUnpaged | EIBYData | EIBYUnpaged,
	/* 031 */ EIBYAlias | EIBYFile,
	/* 032 */ EIBYAlias | EMMPPaged | EIBYFile,
	/* 033 */ EIBYAlias | EMMPUnpaged | EIBYFile,
	/* 034 */ EIBYAlias | EIBYFileCompress,
	/* 035 */ EIBYAlias | EMMPPaged | EIBYFileCompress,
	/* 036 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress,
	/* 037 */ EIBYAlias | EIBYFileCompress,
	/* 038 */ EIBYAlias | EMMPPaged | EIBYFileCompress,
	/* 039 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress,
	/* 040 */ EIBYAlias | EIBYFileCompress,
	/* 041 */ EIBYAlias | EMMPPaged | EIBYFileCompress,
	/* 042 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress,
	/* 043 */ EIBYAlias | EIBYFile | EMMPCompressTarget,
	/* 044 */ EIBYAlias | EMMPPaged | EIBYFile | EMMPNoCompressTarget,
	/* 045 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYFileCompress | EIBYPaged,
	/* 046 */ EIBYAlias | EIBYData,
	/* 047 */ EIBYAlias | EMMPPaged | EIBYData,
	/* 048 */ EIBYAlias | EMMPUnpaged | EIBYData,
	/* 049 */ EIBYAlias | EIBYFile | EIBYPaged,
	/* 050 */ EIBYAlias | EMMPPaged | EIBYFile | EIBYPaged,
	/* 051 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYPaged,
	/* 052 */ EIBYAlias | EIBYFile | EIBYUnpaged,
	/* 053 */ EIBYAlias | EMMPPaged | EIBYFile | EIBYUnpaged,
	/* 054 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYUnpaged,
	/* 055 */ EIBYAlias | EIBYData | EIBYPaged,
	/* 056 */ EIBYAlias | EMMPPaged | EIBYData | EIBYPaged,
	/* 057 */ EIBYAlias | EMMPUnpaged | EIBYData | EIBYPaged,
	/* 058 */ EIBYAlias | EIBYData | EIBYUnpaged,
	/* 059 */ EIBYAlias | EMMPPaged | EIBYData | EIBYUnpaged,
	/* 060 */ EIBYAlias | EMMPUnpaged | EIBYData | EIBYUnpaged
	};
const TUint testDllAttr[] =
	{
	/* 000 - does not exist */ ENone,
	/* 001 */ EIBYFile,
	/* 002 */ EMMPPaged | EIBYFile,
	/* 003 */ EMMPUnpaged | EIBYFile,
	/* 004 */ EIBYFileCompress,
	/* 005 */ EMMPPaged | EIBYFileCompress,
	/* 006 */ EMMPUnpaged | EIBYFileCompress,
	/* 007 */ EDLLWritableStaticData,
	/* 008 */ EMMPPaged | EDLLWritableStaticData,
	/* 009 */ EMMPUnpaged | EDLLWritableStaticData,
	/* 010 */ EIBYFileCompress,
	/* 011 */ EMMPPaged | EIBYFileCompress,
	/* 012 */ EMMPUnpaged | EIBYFileCompress,
	/* 013 */ EIBYFile | EMMPCompressTarget,
	/* 014 */ EMMPPaged | EIBYFile | EMMPNoCompressTarget,
	/* 015 */ EMMPUnpaged | EIBYFile | EIBYFileCompress | EIBYPaged,
	/* 016 */ EIBYData,
	/* 017 */ EMMPPaged | EIBYData,
	/* 018 */ EMMPUnpaged | EIBYData,
	/* 019 */ EIBYFile | EIBYPaged,
	/* 020 */ EMMPPaged | EIBYFile | EIBYPaged,
	/* 021 */ EMMPUnpaged | EIBYFile | EIBYPaged,
	/* 022 */ EIBYFile | EIBYUnpaged,
	/* 023 */ EMMPPaged | EIBYFile | EIBYUnpaged,
	/* 024 */ EMMPUnpaged | EIBYFile | EIBYUnpaged,
	/* 025 */ EIBYData | EIBYPaged,
	/* 026 */ EMMPPaged | EIBYData | EIBYPaged,
	/* 027 */ EMMPUnpaged | EIBYData | EIBYPaged,
	/* 028 */ EIBYData | EIBYUnpaged,
	/* 029 */ EMMPPaged | EIBYData | EIBYUnpaged,
	/* 030 */ EMMPUnpaged | EIBYData | EIBYUnpaged,
	/* 031 */ EIBYAlias | EIBYFile,
	/* 032 */ EIBYAlias | EMMPPaged | EIBYFile,
	/* 033 */ EIBYAlias | EMMPUnpaged | EIBYFile,
	/* 034 */ EIBYAlias | EIBYFileCompress,
	/* 035 */ EIBYAlias | EMMPPaged | EIBYFileCompress,
	/* 036 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress,
	/* 037 */ EIBYAlias | EDLLWritableStaticData,
	/* 038 */ EIBYAlias | EMMPPaged | EDLLWritableStaticData,
	/* 039 */ EIBYAlias | EMMPUnpaged | EDLLWritableStaticData,
	/* 040 */ EIBYAlias | EIBYFileCompress,
	/* 041 */ EIBYAlias | EMMPPaged | EIBYFileCompress,
	/* 042 */ EIBYAlias | EMMPUnpaged | EIBYFileCompress,
	/* 043 */ EIBYAlias | EIBYFile | EMMPCompressTarget,
	/* 044 */ EIBYAlias | EMMPPaged | EIBYFile | EMMPNoCompressTarget,
	/* 045 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYFileCompress | EIBYPaged,
	/* 046 */ EIBYAlias | EIBYData,
	/* 047 */ EIBYAlias | EMMPPaged | EIBYData,
	/* 048 */ EIBYAlias | EMMPUnpaged | EIBYData,
	/* 049 */ EIBYAlias | EIBYFile | EIBYPaged,
	/* 050 */ EIBYAlias | EMMPPaged | EIBYFile | EIBYPaged,
	/* 051 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYPaged,
	/* 052 */ EIBYAlias | EIBYFile | EIBYUnpaged,
	/* 053 */ EIBYAlias | EMMPPaged | EIBYFile | EIBYUnpaged,
	/* 054 */ EIBYAlias | EMMPUnpaged | EIBYFile | EIBYUnpaged,
	/* 055 */ EIBYAlias | EIBYData | EIBYPaged,
	/* 056 */ EIBYAlias | EMMPPaged | EIBYData | EIBYPaged,
	/* 057 */ EIBYAlias | EMMPUnpaged | EIBYData | EIBYPaged,
	/* 058 */ EIBYAlias | EIBYData | EIBYUnpaged,
	/* 059 */ EIBYAlias | EMMPPaged | EIBYData | EIBYUnpaged,
	/* 060 */ EIBYAlias | EMMPUnpaged | EIBYData | EIBYUnpaged
	};

void InitNThreadID()
	{
	_LIT(KThreadName, "ARandomThreadName");
	btrace.SetFilter(BTrace::EThreadIdentification, ETrue);
	btrace.Empty();
	btrace.SetMode(RBTrace::EEnable);
	// rename the current thread to force a ThreadID trace
	User::RenameThread(KThreadName);
	btrace.SetMode(0);
	TInt size;
	TUint8* pDataStart;
	TUint8* pCurrentRecord;
	// extract the nano-kernel thread ID from the trace
	while ((size = btrace.GetData(pDataStart)) != 0)
		{
		pCurrentRecord = pDataStart;
		while (pCurrentRecord - pDataStart < size)
			{
			TInt extensionCount = 4 * (
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EHeader2Present ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestampPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestamp2Present ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EContextIdPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EPcPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EExtraPresent ? 1 : 0));
			//
			if ((pCurrentRecord[BTrace::ECategoryIndex] == BTrace::EThreadIdentification) && (pCurrentRecord[BTrace::ESubCategoryIndex] == BTrace::EThreadName))
				{
				TBuf<255> threadName;
				threadName.Format(_L(""));
				for (TUint8* j = pCurrentRecord + 12 + extensionCount; j < pCurrentRecord + *pCurrentRecord; j++)
					{
					threadName.AppendFormat(_L("%c"), *j);
					}
				if (threadName == KThreadName)
					{
					test.Printf(_L("This thread's NThread ID: %08x\n"), LE4(pCurrentRecord + 4 + extensionCount));
					gNThreadId = LE4(pCurrentRecord + 4 + extensionCount);
					}
				}
			pCurrentRecord = BTrace::NextRecord(pCurrentRecord);
			}
		btrace.DataUsed();
		}
	}
	
void LoadExesRom()
	{
	TInt r;
	TBool pass = ETrue;
	r = btrace.ResizeBuffer(32768); // 32k should be large enough
	TEST_EQ(r, KErrNone);
	btrace.SetFilter(BTrace::EPaging, ETrue);
	btrace.SetFilter(BTrace::EThreadIdentification, ETrue);
	btrace.SetMode(0);
	
	for (TInt i = 1; i <= 60; i++)
		{
		TBuf<255> filename;
		filename.Format(_L("Z:\\SYS\\BIN\\DPEXE%03d.EXE"), i);
	
		test.Printf(_L("Loading %S... "), &filename);
		
		TBool paged = EFalse;
		TBool inRom = EFalse;
		
		TUint32 nthreadAddr = 0;
		TBuf<255> processName;
		
		if (fs.IsFileInRom(filename) != NULL)
			{
			inRom = ETrue;
			}
		else
			{
			inRom = EFalse;
			}
		
		// Ensure that the paging live list is empty
		r = DPTest::FlushCache();
		if (gIsRomDemangPagingEnabled)
			{
			TEST_EQ(r, KErrNone);
			}
		else
			{
			TEST_EQ(r, KErrNotSupported);
			}
		
		btrace.Empty(); // empty the BTrace buffer
		btrace.SetMode(RBTrace::EEnable);
		RProcess proc;
		r = proc.Create(filename, _L(""));
			
		if ((testExeAttr[i] & EIBYAlias) && (testExeAttr[i] & EIBYData) && (gIsRomDemangPagingEnabled))
		// There cannot be aliases mapping to "data" files since they are moved to ROFS if the ROM is paged
			{
			TEST_EQ(r, KErrNotFound);
			continue;
			}
		else
			{
			TEST_EQ(r, KErrNone);
			}
		
		// Resume the process and wait until it completes
		TRequestStatus ps;
		proc.Logon(ps);
		proc.Resume();
		proc.Close();
		User::WaitForRequest(ps);
		
		// Disable trace
		btrace.SetMode(0);
		
		TInt size;
		TUint8* pDataStart;
		TUint8* pCurrentRecord;
		
		// We have a while loop here, in the unlikely case that our trace is fragmented	
		while ((size = btrace.GetData(pDataStart)) != 0)
			{
			pCurrentRecord = pDataStart;
			while (pCurrentRecord - pDataStart < size)
				{
				// Number of bytes used by the BTrace extensions
				TInt extensionCount = 4 * (
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EHeader2Present ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestampPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestamp2Present ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EContextIdPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EPcPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EExtraPresent ? 1 : 0));
				
				if ((pCurrentRecord[BTrace::ECategoryIndex] == BTrace::EThreadIdentification) && (pCurrentRecord[BTrace::ESubCategoryIndex] == BTrace::EProcessName))
				// Process renamed
					{
					processName.Format(_L(""));
					for (TUint8* j = pCurrentRecord + 12 + extensionCount; j < pCurrentRecord + *pCurrentRecord; j++)
						{
						processName.AppendFormat(_L("%c"), *j);
						}
					TBuf<255> expected;
					expected.Format(_L("dpexe%03d.exe[%08x]%04x"), i, 0, 1);
					
					if (processName == expected)
						{
						nthreadAddr = LE4(pCurrentRecord + 4 + extensionCount);
						}					
					}
				if ((pCurrentRecord[BTrace::ECategoryIndex] == BTrace::EPaging) && (LE4(pCurrentRecord + 8) == nthreadAddr))
				/* The main thread of the test process tries to page in the test executable	*/
					{
					paged = ETrue;
					}
				pCurrentRecord = BTrace::NextRecord(pCurrentRecord); // move on to the next record
				}
			btrace.DataUsed();
			}
		
		if (paged)
			test.Printf(_L("paged!\n"));
		else
			test.Printf(_L("not paged!\n"));
		
		if (!gIsRomDemangPagingEnabled)
		// ROM paging disabled. All files are in ROM and unpaged
			{
			test.Printf(_L("ROM Paging disabled: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (testExeAttr[i] & EIBYData)
			// data - if ROM paged, then these executables will be moved to ROFS
			// these are always expected to be RAM loaded
			{
			test.Printf(_L("EXE is DATA in ROFS\n"));
			TEST_CONDITION(!inRom);
			}
		else if (testExeAttr[i] & EIBYFileCompress)
			// Compression format specified in the IBY file
			// These are expected to be stay in ROM, but will be RAM-loaded
			{
			test.Printf(_L("EXE has own compression method: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		// from this point onwards, all executables can potentially be paged - paging policy takes precedence
		else if (gPagingPolicy == EKernelConfigCodePagingPolicyNoPaging)
			{
			test.Printf(_L("Paging policy is No Paging: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (gPagingPolicy == EKernelConfigCodePagingPolicyAlwaysPage)
			{
			test.Printf(_L("Paging policy is No Paging: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		// from this point onwards, paging policy is either Default Paged or Default Unpaged - paging override takes precedence
		else if (gPagingOverride == EKernelConfigCodePagingPolicyNoPaging)
			{
			test.Printf(_L("Paging override is No Paging: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (gPagingOverride == EKernelConfigCodePagingPolicyAlwaysPage)
			{
			test.Printf(_L("Paging override is Always Page: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		// from this point onwards, paging policy and override are either Default Paged or Default Unpaged - IBY setting takes precedence
		else if (testExeAttr[i] & EIBYPaged)
			{
			test.Printf(_L("Paged keyword in OBY: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		else if (testExeAttr[i] & EIBYUnpaged)
			{
			test.Printf(_L("Unpaged keyword in OBY: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		// Next, MMP setting takes precedence
		else if (testExeAttr[i] & EMMPPaged)
			{
			test.Printf(_L("Paged keyword in MMP: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		else if (testExeAttr[i] & EMMPUnpaged)
			{
			test.Printf(_L("Unpaged keyword in MMP: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		// The test exe has no attribute. Paging overright default paging mode takes precedence
		else if (gPagingOverride == EKernelConfigCodePagingPolicyDefaultUnpaged)
			{
			test.Printf(_L("Paging override is Default Unpaged: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (gPagingOverride == EKernelConfigCodePagingPolicyDefaultPaged)
			{
			test.Printf(_L("Paging override is Default Paged: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		// Paging policy default paging mode takes precedence
		else if (gPagingPolicy == EKernelConfigCodePagingPolicyDefaultUnpaged)
			{
			test.Printf(_L("Paging policy is Default Unpaged: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (gPagingPolicy == EKernelConfigCodePagingPolicyDefaultPaged)
			{
			test.Printf(_L("Paging policy is Default paged: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		// ROM Paging enabled without a default paging policy - this should not happen (default policy is No Paging)
		else
			{
			test.Printf(_L("No paging policy!\n"));
			test(EFalse);
			}
		}
	test(pass);
	}
	

void LoadDllsRom()
	{
	TInt r;
	TBool pass = ETrue;
	r = btrace.ResizeBuffer(32768); // 32k should be large enough
	TEST_EQ(r, KErrNone);
	btrace.SetFilter(BTrace::EPaging, ETrue);
	btrace.SetFilter(BTrace::EThreadIdentification, ETrue);
	btrace.SetMode(0);
	
	for (TInt i = 1; i <= 60; i++)
		{
		TBuf<255> filename;
		filename.Format(_L("Z:\\SYS\\BIN\\DPDLL%03d.DLL"), i);
	
		test.Printf(_L("Loading %S... "), &filename);
		
		TBool paged = EFalse;
		TBool inRom = EFalse;
		
		TUint libLoadEnd;
		TInt filesize;
		
		TUint8* addr;
		if ((addr = fs.IsFileInRom(filename)) != NULL)
			{
			inRom = ETrue;
			}
		else
			{
			inRom = EFalse;
			}
		
		RFile file;
		r = file.Open(fs, filename, EFileRead);
		if ((testDllAttr[i] & EIBYAlias) && (testDllAttr[i] & EIBYData) && (gIsRomDemangPagingEnabled))
		// There cannot be aliases mapping to "data" files since they are moved to ROFS if the ROM is paged
			{
			TEST_EQ(r, KErrNotFound);
			continue;
			}
		else
			{
			TEST_EQ(r, KErrNone);
			}
		r = file.Size(filesize);
		TEST_EQ(r, KErrNone);
		file.Close();
		
		// Ensure that the paging live list is empty
		r = DPTest::FlushCache();
		if (gIsRomDemangPagingEnabled)
			{
			TEST_EQ(r, KErrNone);
			}
		else
			{
			TEST_EQ(r, KErrNotSupported);
			}
		
		btrace.Empty(); // empty the BTrace buffer
		btrace.SetMode(RBTrace::EEnable);
		RLibrary lib;
		r = lib.Load(filename);
		libLoadEnd = User::FastCounter();
		
		TEST_EQ(r, KErrNone);
		
		TLibraryFunction function1;
		TLibraryFunction function2;
		TLibraryFunction function3;
		TLibraryFunction function4;
		
		function1 = lib.Lookup(1);
		function2 = lib.Lookup(2);
		function3 = lib.Lookup(3);
		function4 = lib.Lookup(4);
		
		test(function1 != NULL);
		test(function2 != NULL);
		test(function3 != NULL);
		test(function4 == NULL);
		
		// Resume the process and wait until it completes
	
		function1();
		function2();
		function3();
		
		lib.Close();
		
		//processResumeStart = User::FastCounter();
		//processResumeEnd = User::FastCounter();
		
		// Disable trace
		btrace.SetMode(0);
		
		TInt size;
		TUint8* pDataStart;
		TUint8* pCurrentRecord;
		
		// We have a while loop here, in the unlikely case that our trace is fragmented	
		while ((size = btrace.GetData(pDataStart)) != 0)
			{
			pCurrentRecord = pDataStart;
			while (pCurrentRecord - pDataStart < size)
				{
				// Number of bytes used by the BTrace extensions
				TInt extensionCount = 4 * (
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EHeader2Present ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestampPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::ETimestamp2Present ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EContextIdPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EPcPresent ? 1 : 0) +
				(pCurrentRecord[BTrace::EFlagsIndex] & BTrace::EExtraPresent ? 1 : 0));

				if ((pCurrentRecord[BTrace::ECategoryIndex] == BTrace::EPaging)
					&& (pCurrentRecord[BTrace::ESubCategoryIndex] == BTrace::EPagingPageInBegin)
					&& (LE4(pCurrentRecord + 4) > libLoadEnd)
					&& (LE4(pCurrentRecord + extensionCount) == gNThreadId)
					&& (LE4(pCurrentRecord + 4 + extensionCount) >= (TUint32) addr)
					&& (LE4(pCurrentRecord + 4 + extensionCount) < ((TUint32) addr) + filesize))
				// If the DLL is paged in under this thread after it's been RLibrary::Load'ed, then we assume the DLL is paged
					{
					paged = ETrue;
					}
				pCurrentRecord = BTrace::NextRecord(pCurrentRecord); // move on to the next record
				}
			btrace.DataUsed();
			}

		if (paged)
			test.Printf(_L("paged!\n"));
		else
			test.Printf(_L("not paged!\n"));

		if (!gIsRomDemangPagingEnabled)
		// ROM paging disabled. All files are in ROM and unpaged
			{
			test.Printf(_L("ROM Paging disabled: shouldn't be paged\n"));
			test(inRom);
			TEST_CONDITION(!paged);
			}
		else if (testDllAttr[i] & EIBYData)
			// data - if ROM paged, then these executables will be moved to ROFS
			// these are always expected to be RAM loaded
			{
			test.Printf(_L("DLL is DATA in ROFS: shouldn't be paged\n"));
			TEST_CONDITION(!inRom);
			TEST_CONDITION(!paged);
			}
		else if (testDllAttr[i] & EIBYFileCompress)
			// Compression format specified in the IBY file
			// These are expected to be stay in ROM, but will be RAM-loaded
			{
			test.Printf(_L("DLL has own compression method: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		// from this point onwards, all executables can potentially be paged - paging policy takes precedence
		else if (gPagingPolicy == EKernelConfigCodePagingPolicyNoPaging)
			{
			test.Printf(_L("Paging policy is No Paging: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (gPagingPolicy == EKernelConfigCodePagingPolicyAlwaysPage)
			{
			test.Printf(_L("Paging policy is Always Page: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		// from this point onwards, paging policy is either Default Paged or Default Unpaged - paging override takes precedence
		else if (gPagingOverride == EKernelConfigCodePagingPolicyNoPaging)
			{
			test.Printf(_L("Paging override is No Paging: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (gPagingOverride == EKernelConfigCodePagingPolicyAlwaysPage)
			{
			test.Printf(_L("Paging override is Always Page: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		// from this point onwards, paging policy and override are either Default Paged or Default Unpaged - IBY setting takes precedence
		else if (testDllAttr[i] & EIBYPaged)
			{
			test.Printf(_L("Paged keyword in OBY: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		else if (testDllAttr[i] & EIBYUnpaged)
			{
			test.Printf(_L("Unpaged keyword in OBY: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		// Next, MMP setting takes precedence
		else if (testDllAttr[i] & EMMPPaged)
			{
			test.Printf(_L("Paged keyword in MMP: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		else if (testDllAttr[i] & EMMPUnpaged)
			{
			test.Printf(_L("Unpaged keyword in MMP: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		// The test exe has no attribute. Paging overright default paging mode takes precedence
		else if (gPagingOverride == EKernelConfigCodePagingPolicyDefaultUnpaged)
			{
			test.Printf(_L("Paging override is Default Unpaged: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (gPagingOverride == EKernelConfigCodePagingPolicyDefaultPaged)
			{
			test.Printf(_L("Paging override is Default Paged: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		// Paging policy default paging mode takes precedence
		else if (gPagingPolicy == EKernelConfigCodePagingPolicyDefaultUnpaged)
			{
			test.Printf(_L("Paging policy is Default Unpaged: shouldn't be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(!paged);
			}
		else if (gPagingPolicy == EKernelConfigCodePagingPolicyDefaultPaged)
			{
			test.Printf(_L("Paging policy is Default paged: should be paged\n"));
			TEST_CONDITION(inRom);
			TEST_CONDITION(paged);
			}
		// ROM Paging enabled without a default paging policy - this should not happen (default policy is No Paging)
		else
			{
			test.Printf(_L("No paging policy!\n"));
			test(EFalse);
			}
		}
	test(pass);
	}

GLDEF_C TInt E32Main()
	{
	TInt r;
	test.Title();
	test.Start(_L("Check environment"));
	
	// Open the BTrace handler
	r = btrace.Open();
	TEST_EQ(r, KErrNone);
	
	// capture the NThread ID of the main thread of the current process
	InitNThreadID();
	test(gNThreadId != 0);
	
	gPagingPolicy = E32Loader::PagingPolicy();
	gPagingOverride = -1;
	
	r = fs.Connect();
	TEST_EQ(r, KErrNone);
	
	if (fs.IsFileInRom(_L("\\ovr_nopaging")) != NULL)
		{
		gPagingOverride = EKernelConfigCodePagingPolicyNoPaging;
		}
	if (fs.IsFileInRom(_L("\\ovr_alwayspage")) != NULL)
		{
		gPagingOverride = EKernelConfigCodePagingPolicyAlwaysPage;
		}
	if (fs.IsFileInRom(_L("\\ovr_defaultunpaged")) != NULL)
		{
		gPagingOverride = EKernelConfigCodePagingPolicyDefaultUnpaged;
		}
	if (fs.IsFileInRom(_L("\\ovr_defaultpaged")) != NULL)
		{
		gPagingOverride = EKernelConfigCodePagingPolicyDefaultPaged;
		}
	if (fs.IsFileInRom(_L("\\pcy_nopaging")) != NULL)
		{
		gPagingPolicy = EKernelConfigCodePagingPolicyNoPaging;
		}
	if (fs.IsFileInRom(_L("\\pcy_alwayspage")) != NULL)
		{
		gPagingPolicy = EKernelConfigCodePagingPolicyAlwaysPage;
		}
	if (fs.IsFileInRom(_L("\\pcy_defaultunpaged")) != NULL)
		{
		gPagingPolicy = EKernelConfigCodePagingPolicyDefaultUnpaged;
		}
	if (fs.IsFileInRom(_L("\\pcy_defaultpaged")) != NULL)
		{
		gPagingPolicy = EKernelConfigCodePagingPolicyDefaultPaged;
		}
		
	gIsRomDemangPagingEnabled = (fs.IsFileInRom(_L("Z:\\SYS\\BIN\\DPEXE046.EXE")) == NULL);
		
	test.Printf(_L("Demand Paging Enabled? %d\n"), gIsRomDemangPagingEnabled);
	test.Printf(_L("PagingOverride %d\n"), gPagingOverride);
	test.Printf(_L("PagingPolicy %d\n"), gPagingPolicy);
	
	test.Next(_L("Load ROM EXEs"));
	LoadExesRom();
	test.Next(_L("Load ROM DLLs"));
	LoadDllsRom();
	
	btrace.Close();
	fs.Close();
	test.End();
	test.Close();
	return KErrNone;
	}