--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_tst.cpp Fri Apr 16 16:24:37 2010 +0300
@@ -0,0 +1,466 @@
+// 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:
+// e32test\mmu\t_wsd_tst.cpp
+// Test exporting and importing writable static data in DLLs.
+// This test relies on three dlls:
+// - t_wsd_dl1_[cx][pu] Which is statically linked, and exports both code & data
+// - t_wsd_dl2_[cx][pu] Which is dyanamically loaded, and imports code & writable static data from
+// - t_wsd_dl3_[cx][pu] Which exports code and writable static data
+// The [cx] suffix indicates code-in-RAM vs XIP (ROM), and [pu] indicate paged or unpaged code.
+//
+
+//! @SYMTestCaseID KBASE-T_CODEPAGING-0335
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1110
+//! @SYMTestCaseDesc Demand Paging Code Paging tests.
+//! @SYMTestActions 001 Code paging tests
+//! @SYMTestExpectedResults All tests should pass.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+
+#define __E32TEST_EXTENSION__
+#include <e32test.h>
+#include <e32math.h>
+#include <f32file.h>
+#include <f32dbg.h>
+
+#include "mmudetect.h"
+#include "t_wsd_tst.h"
+
+// Global data /////////////////////////////////////////////////////////////////
+
+_LIT(KSearchPathTemplate, "%c:\\sys\\bin"); // drive letter
+_LIT(KLibraryName, "t_wsd_dl%d_%c%c"); // [23] [cx] [pu]
+
+TInt TheFailure = KErrNone;
+TChar CurrentDrive = 'Z';
+
+void SetCurrentDrive(TChar aDrive)
+ {
+ CurrentDrive = aDrive;
+ }
+
+class TPagingDriveInfo
+ {
+public:
+ TChar iDriveLetter;
+ TDriveInfo iDriveInfo;
+ };
+
+RArray<TPagingDriveInfo> SupportedDrives;
+
+// RTest stuff /////////////////////////////////////////////////////////////////
+
+RTest test(_L("T_WSD"));
+
+#define test_noError(x) { TInt _r = (x); if (_r < 0) HandleError(_r, __LINE__); }
+#define test_notNull(x) { TAny* _a = (TAny*)(x); if (_a == NULL) HandleNull(__LINE__); }
+#define test_equal(e, a) { TInt _e = TInt(e); TInt _a = TInt(a); if (_e != _a) HandleNotEqual(_e, _a, __LINE__); }
+
+void HandleError(TInt aError, TInt aLine)
+ {
+ test.Printf(_L("Error %d\n"), aError);
+ test.operator()(EFalse, aLine);
+ }
+
+void HandleNull(TInt aLine)
+ {
+ test.Printf(_L("Null value\n"));
+ test.operator()(EFalse, aLine);
+ }
+
+void HandleNotEqual(TInt aExpected, TInt aActual, TInt aLine)
+ {
+ test.Printf(_L("Expected 0x%x but got 0x%x\n"), aExpected, aActual);
+ test.operator()(EFalse, aLine);
+ }
+
+// Utility functions ///////////////////////////////////////////////////////////
+
+TPtrC16 GetMediaType(TInt aMediaType)
+ {
+ _LIT(KMediaNotPresent, "MediaNotPresent");
+ _LIT(KMediaUnknown, "MediaUnknown");
+ _LIT(KMediaFloppy, "MediaFloppy");
+ _LIT(KMediaHardDisk, "MediaHardDisk");
+ _LIT(KMediaCdRom, "MediaCdRom");
+ _LIT(KMediaRam, "MediaRam");
+ _LIT(KMediaFlash, "MediaFlash");
+ _LIT(KMediaRom, "MediaRom");
+ _LIT(KMediaRemote, "MediaRemote");
+ _LIT(KMediaNANDFlash, "MediaNANDFlash");
+ _LIT(KMediaUnKnown, "MediaUnKnown");
+
+ switch (aMediaType)
+ {
+ case EMediaNotPresent:
+ return KMediaNotPresent();
+ case EMediaUnknown:
+ return KMediaUnknown();
+ case EMediaFloppy:
+ return KMediaFloppy();
+ case EMediaHardDisk:
+ return KMediaHardDisk();
+ case EMediaCdRom:
+ return KMediaCdRom();
+ case EMediaRam:
+ return KMediaRam();
+ case EMediaFlash:
+ return KMediaFlash();
+ case EMediaRom:
+ return KMediaRom();
+ case EMediaRemote:
+ return KMediaRemote();
+ case EMediaNANDFlash:
+ return KMediaNANDFlash();
+ default:
+ return KMediaUnKnown();
+ }
+ }
+
+// Get the list of testable drives
+void GetSupportedDrives(TBool aVerbose = EFalse)
+ {
+ TUint32 memModelAttributes = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
+ TBool codePagingSupported = (memModelAttributes & EMemModelAttrCodePaging) != 0;
+ TUint32 pagingPolicy = E32Loader::PagingPolicy();
+ TBool pagingPolicyAllowsPaging = pagingPolicy != EKernelConfigCodePagingPolicyNoPaging;
+ test_Equal(codePagingSupported, pagingPolicyAllowsPaging);
+ if (codePagingSupported)
+ test.Printf(_L("Code paging is enabled.\n"));
+ else
+ test.Printf(_L("Code paging is NOT enabled.\n"));
+
+ if (aVerbose)
+ {
+ test.Printf(_L("Available drives:\n"));
+ test.Printf(_L(" Type Attr MedAttr Filesystem\n"));
+ }
+
+ RFs fs;
+ test_noError(fs.Connect());
+
+ TDriveList driveList;
+ TInt r = fs.DriveList(driveList);
+ test_noError(r);
+
+ TBool NandPageableMediaFound = EFalse;
+ for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum)
+ {
+ if (!driveList[drvNum])
+ continue; //-- skip unexisting drive
+
+ TDriveInfo driveInfo;
+ r = fs.Drive(driveInfo, drvNum);
+ test_noError(r);
+
+ TChar ch;
+ r = fs.DriveToChar(drvNum, ch);
+ test_noError(r);
+
+ TBuf<256> fileSystemName;
+ r = fs.FileSystemName(fileSystemName, drvNum);
+ test_noError(r);
+
+ // Decide which drives to exclude:
+ // Locked/nonwritable drives, except the Z: ROM drive
+ // Win32 drives on the emulator
+ // Remote/nonlocal, removable/noninternal, redirected, substed drives
+ // All others are included by default iff code paging is supported
+ // If not, only the Z: ROM/XIP drive is tested
+ _LIT(KWin32FS, "Win32");
+ TBool include = codePagingSupported;
+ if (driveInfo.iDriveAtt & KDriveAttRom)
+ include = (ch == 'Z');
+ else if (driveInfo.iMediaAtt & (KMediaAttWriteProtected|KMediaAttLocked))
+ include = EFalse;
+ else if (fileSystemName == KWin32FS())
+ include = EFalse;
+ else if (driveInfo.iDriveAtt & (KDriveAttRedirected|KDriveAttSubsted|KDriveAttRemovable|KDriveAttRemote))
+ include = EFalse;
+ else if ((KDriveAttInternal|KDriveAttLocal) & ~driveInfo.iDriveAtt)
+ include = EFalse;
+
+ if (include)
+ {
+ TPagingDriveInfo pagingDriveInfo;
+ pagingDriveInfo.iDriveLetter = ch;
+ pagingDriveInfo.iDriveInfo = driveInfo;
+ r = SupportedDrives.Append(pagingDriveInfo);
+ test_noError(r);
+ }
+
+ TBool pageable = EFalse;
+ if (driveInfo.iDriveAtt & KDriveAttPageable)
+ {
+ pageable = ETrue;
+ if (driveInfo.iType == EMediaNANDFlash)
+ NandPageableMediaFound = ETrue;
+ }
+
+ // If we've already found a pageable NAND drive, then assume the
+ // Z: drive is pageable too if it's got a composite file system
+ _LIT(KCompositeName,"Composite");
+ if (NandPageableMediaFound && fileSystemName == KCompositeName())
+ pageable = ETrue;
+
+ if (aVerbose)
+ {
+ TPtrC16 mediaType = GetMediaType(driveInfo.iType);
+ _LIT(KPageable, "pageable");
+ test.Printf(_L("%c %c: %16S %08x %08x %10S %S\n"),
+ include ? '*' : ' ', (TUint)ch, &mediaType,
+ driveInfo.iDriveAtt, driveInfo.iMediaAtt,
+ &fileSystemName, (pageable ? &KPageable : &KNullDesC));
+ }
+ }
+
+ fs.Close();
+ }
+
+const TDesC& LibrarySearchPath(TChar aDrive)
+ {
+ static TBuf<64> path;
+ path.Format(KSearchPathTemplate, (TUint)aDrive);
+ return path;
+ }
+
+const TDesC& LibraryName(TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+ {
+ // this gives DLL#2 a different name on each drive so we can be sure we're loading the right one
+ static TBuf<64> name;
+ name.Format(KLibraryName, aLibNo, aRam ? 'c' : 'x', aPaged ? 'p' : 'u');
+ if (aLibNo == 2 && aDrive != 'Z')
+ name.AppendFormat(_L("_%c"), (TUint)aDrive);
+ return name;
+ }
+
+const TDesC& LibraryFilename(TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+ {
+ static TBuf<64> filename;
+ filename = LibrarySearchPath(aDrive);
+ filename.AppendFormat(_L("\\%S.dll"), &LibraryName(aDrive, aLibNo, aRam, aPaged));
+ return filename;
+ }
+
+TInt LoadSpecificLibrary(RLibrary& aLibrary, TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+ {
+ const TDesC& path = LibrarySearchPath(aDrive);
+ const TDesC& name = LibraryName(aDrive, aLibNo, aRam, aPaged);
+ TInt err = aLibrary.Load(name, path);
+ TBuf<256> message;
+ message.Format(_L("Loading %S\\%S.dll returns %d\n"), &path, &name, err);
+ test.Printf(message);
+ return err;
+ }
+
+// Test functions //////////////////////////////////////////////////////////////
+
+void CopyDllToCurrentDrive(RFs& aFs, TBool aPaged, TInt aLibNo)
+ {
+ TBuf<64> source = LibraryFilename('Z', aLibNo, ETrue, aPaged);
+ TBuf<64> dest = LibraryFilename(CurrentDrive, aLibNo, ETrue, aPaged);
+ test.Printf(_L("Copying %S to %S\n"), &source, &dest);
+
+ TInt r = aFs.MkDirAll(dest);
+ test(r == KErrNone || r == KErrAlreadyExists);
+
+ TBuf<64> tempName(dest);
+ tempName.Append(_L(".tmp"));
+
+ RFile in, out, temp;
+ test_noError(in.Open(aFs, source, EFileRead));
+ test_noError(out.Replace(aFs, dest, EFileWrite));
+ test_noError(temp.Replace(aFs, tempName, EFileWrite));
+
+ const TInt KBufferSize = 3333;
+ TBuf8<KBufferSize> buffer;
+
+ test_noError(temp.Write(buffer));
+ test_noError(temp.Flush());
+
+ TInt size;
+ test_noError(in.Size(size));
+ TInt pos = 0;
+ while (pos < size)
+ {
+ test_noError(in.Read(buffer));
+ test_noError(out.Write(buffer));
+ test_noError(out.Flush());
+ test_noError(temp.Write(buffer));
+ test_noError(temp.Flush());
+ pos += buffer.Length();
+ }
+
+ out.SetAtt(KEntryAttNormal, KEntryAttReadOnly|
+ KEntryAttHidden|
+ KEntryAttSystem|
+ KEntryAttArchive|
+ KEntryAttXIP);
+
+ in.Close();
+ out.Close();
+ temp.Close();
+ }
+
+void CopyDllsToCurrentDrive()
+ {
+ RFs fs;
+ test_noError(fs.Connect());
+
+ CopyDllToCurrentDrive(fs, EFalse, 2); // Unpaged library 2
+ CopyDllToCurrentDrive(fs, EFalse, 3); // Unpaged library 3
+ CopyDllToCurrentDrive(fs, ETrue, 2); // Paged library 2
+ CopyDllToCurrentDrive(fs, ETrue, 3); // Paged library 3
+
+ fs.Close();
+ }
+
+void EraseDllsFromCurrentDrive()
+ {
+ RFs fs;
+ test_noError(fs.Connect());
+
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ test_notNull(cleanup);
+
+ CFileMan* fileMan = NULL;
+ TRAPD(r, fileMan = CFileMan::NewL(fs));
+ test_noError(r);
+
+ TBuf<64> libdir = LibrarySearchPath(CurrentDrive);
+ test.Printf(_L("Erasing %S\n"), &libdir);
+ fileMan->RmDir(libdir);
+
+ delete fileMan;
+ delete cleanup;
+ fs.Close();
+ }
+
+void CheckRelocatableData(RLibrary& library)
+ {
+ TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal);
+ test_notNull(func);
+
+ TInt size;
+ void* codeAddr;
+ void* dataAddr;
+ void*** dataPtrPtr = (void***)func(size, codeAddr, dataAddr);
+ void **dp = (void **)dataAddr;
+
+ for (TInt i = 0; i < size/4; i += 2)
+ {
+ test_equal(dp[i], codeAddr);
+ test_equal(dp[i+1], dataAddr);
+ }
+
+ test_equal(*dataPtrPtr, dp);
+ }
+
+void CheckWritableStaticData(RLibrary& library)
+ {
+ TInt (*func)(void) = (TInt (*)(void))library.Lookup(KCheckWritableStaticDataFunctionOrdinal);
+ RDebug::Printf("CheckWritableStaticData() is export %d at %08x", KCheckWritableStaticDataFunctionOrdinal, func);
+ test_notNull(func);
+ TInt err = func();
+ RDebug::Printf("CheckWritableStaticData() returned %d", err);
+ // test_noError(err);
+ if (TheFailure == KErrNone)
+ TheFailure = err;
+ }
+
+void RunPerDriveTests(TBool aPaged, TBool aRam)
+ {
+ TBuf<64> message = _L("Running ");
+ if (!aPaged)
+ message.Append(_L("un"));
+ message.AppendFormat(_L("paged R%cM tests on drive %c:"),
+ aRam ? 'A' : 'O', (TUint)CurrentDrive);
+ test.Next(message);
+
+ RFs fs;
+ test_noError(fs.Connect());
+ fs.SetDebugRegister(KFLDR);
+
+ // Explicitly loading dl2 will implicitly load dl3 as well
+ RLibrary dl2;
+ test_noError(LoadSpecificLibrary(dl2, CurrentDrive, 2, aRam, aPaged));
+ CheckRelocatableData(dl2);
+ CheckWritableStaticData(dl2);
+ dl2.Close();
+
+ fs.SetDebugRegister(0);
+ fs.Close();
+ }
+
+TInt E32Main()
+ {
+ test.Title();
+ test.Start(_L("WSD tests"));
+
+ // Check static linkage to dl1
+ test_noError(CheckExportedDataAddress(&ExportedData));
+
+ GetSupportedDrives(ETrue);
+ test(SupportedDrives.Count() > 0);
+
+ // Turn off evil lazy dll unloading
+ RLoader l;
+ test(l.Connect()==KErrNone);
+ test(l.CancelLazyDllUnload()==KErrNone);
+ l.Close();
+
+ // Make sure there aren't any DLLs left over from earlier tests
+ TInt i = SupportedDrives.Count();
+ while (--i >= 0)
+ {
+ SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+ if (CurrentDrive != 'Z')
+ EraseDllsFromCurrentDrive();
+ }
+
+ // We want to test all supported drives in order of increasing priority, so
+ // that the CurrentDrive is always the hghest priority of those tested so far.
+ // Therefore, if Z (XIP ROM, lowest priority) is a valid test drive, do it first
+ i = SupportedDrives.Count();
+ if (--i >= 0)
+ {
+ SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+ if (CurrentDrive == 'Z')
+ {
+ // ROM (XIP) tests can only be run from Z:
+ RunPerDriveTests(EFalse, EFalse); // Unpaged ROM
+ RunPerDriveTests(ETrue, EFalse); // Paged ROM
+ RunPerDriveTests(EFalse, ETrue); // Unpaged RAM
+ RunPerDriveTests(ETrue, ETrue); // Paged RAM
+ }
+ }
+
+ // Now run the RAM-based versions from each remaining drive in turn
+ for (i = 0; i < SupportedDrives.Count(); ++i)
+ {
+ SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+ if (CurrentDrive != 'Z')
+ {
+ CopyDllsToCurrentDrive();
+ RunPerDriveTests(EFalse, ETrue); // Unpaged RAM
+ RunPerDriveTests(ETrue, ETrue); // Paged RAM
+ }
+ }
+
+ test_noError(TheFailure);
+ test.End();
+ return 0;
+ }
+