kerneltest/f32test/demandpaging/integtest/src/t_dpattr.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/demandpaging/integtest/src/t_dpattr.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,823 @@
+// 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;
+	}