--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/filesystem/fat/t_mount.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,1312 @@
+// Copyright (c) 1996-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:
+// f32test\server\t_mount.cpp
+// Testing some issues connected with mounting/dismounting file fystems, drives finalisation etc.
+//
+//
+
+/**
+ @file
+*/
+
+#define __E32TEST_EXTENSION__
+
+#include <f32file.h>
+#include <e32test.h>
+#include <e32math.h>
+#include <e32property.h>
+#include <f32dbg.h>
+
+#include "t_server.h"
+#include "fat_utils.h"
+
+using namespace Fat_Test_Utils;
+
+#ifdef __VC32__
+ // Solve compilation problem caused by non-English locale
+ #pragma setlocale("english")
+#endif
+
+RTest test(_L("T_Mount"));
+
+static TInt gDriveNum=-1; ///< drive number we are dealing with
+static TInt64 gRndSeed;
+
+
+const TInt KBM_Repetitions = 5; ///< number of repetitions for BM testing
+const TUint32 KCheckFileSize = 533; ///< size of the small file to be deleted
+
+_LIT(KFileNameFirst, "\\FIRST%d.DAT");
+_LIT(KFileNameMiddle, "\\MID%d.DAT");
+_LIT(KFileNameLast, "\\LAST%d.DAT");
+_LIT(KFileNameFiller, "\\FILL%d.DAT");
+
+typedef void (*TStressFN)(TInt); //-- pointer to the FAT mount stress function
+
+
+//-------------------------------------------------------------------
+//-- debug bit flags that may be set in the property which controls FAT volume mounting
+
+const TUid KThisTestSID={0x10210EB3}; ///< this EXE SID
+
+const TUint32 KMntProp_EnableALL = 0x00000000; //-- enable all operations
+
+#ifdef _DEBUG
+
+const TUint32 KMntProp_DisableALL = 0xFFFFFFFF; //-- disable all operations
+const TUint32 KMntProp_Disable_FsInfo = 0x00000001; //-- mask for disabling/enabling FSInfo information
+const TUint32 KMntProp_Disable_FatBkGndScan = 0x00000002; //-- mask for disabling/enabling FAT background scanner
+
+#endif
+
+//-------------------------------------------------------------------
+
+/** set a debug property value, which then wiil be read by FAT fsy */
+void SetFsyDebugFlag(TInt aDriveNo, TUint32 aFlags)
+{
+ TInt nRes;
+
+ nRes = RProperty::Set(KThisTestSID, aDriveNo, aFlags);
+ test_KErrNone(nRes);
+}
+
+//-------------------------------------------------------------------
+/**
+ format the volume and read the boot sector
+*/
+static void FormatVolume(TBool aQuickFormat)
+{
+ TInt nRes;
+
+ #if 0
+ //-- FAT32 SPC:1; for the FAT32 testing on the emulator
+ (void)aQuickFormat;
+
+ #ifdef __EPOC32__
+ test.Printf(_L("This is emulator configuration!!!!\n"));
+ test(0);
+ #endif
+
+ TFatFormatParam fp;
+ fp.iFatType = EFat32;
+ fp.iSecPerCluster = 1;
+ nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue, &fp); //-- always quick; doesn't matter for the emulator
+ #else
+ nRes = FormatFatDrive(TheFs, CurrentDrive(), aQuickFormat);
+ #endif
+
+ test_KErrNone(nRes);
+
+}
+
+//-------------------------------------------------------------------
+
+/**
+ Prepare FAT volume for mounting performance testing
+
+ 1. quick format the drive
+ 2. create KBM_Repetitions files in the beginning (first files)
+ 3. create KMaxFillFiles/2 large files (they take about 40% of the volume);
+ 4. create KBM_Repetitions files (middle files)
+ 5. create KMaxFillFiles/2 large files (they take other 40% of the volume);
+ 6. create KBM_Repetitions files (last files)
+
+ @return ETrue if everythis is OK
+*/
+TBool PrepareVolumeForBM()
+{
+ test.Printf(_L("Prepare the volume for BM testing...\n"));
+
+ TInt nRes;
+ TInt i;
+
+ //-- 1. quick format the drive
+ FormatVolume(ETrue);
+
+
+ if(!Is_Fat32(TheFs, gDriveNum))
+ {
+ test.Printf(_L("This test requires FAT32 ! Skipping.\n"));
+ return EFalse;
+ }
+
+ TVolumeInfo volInfo;
+ nRes = TheFs.Volume(volInfo, gDriveNum);
+ test_KErrNone(nRes);
+
+ //-- the files will take 80% of the drive space
+ const TInt KMaxFillFiles = 100;
+ const TUint32 KFillFileSz = (TUint32)((volInfo.iFree*8) / (10*KMaxFillFiles));
+
+ //-- 2. create KBM_Repetitions files in the very begining (occupies first FAT entries)
+ TBuf<64> buf;
+
+ for(i=0; i<KBM_Repetitions; ++i)
+ {
+ buf.Format(KFileNameFirst, i);
+ nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
+ test_KErrNone(nRes);
+ }
+
+ //-- 3. Fill the FAT with entries and cteate a file in the middle
+ const TInt nHalf1 = KMaxFillFiles / 2;
+
+ for(i=0; i<nHalf1; ++i)
+ {
+ buf.Format(KFileNameFiller, i);
+ nRes = CreateEmptyFile(TheFs, buf, KFillFileSz);
+ test_KErrNone(nRes);
+ }
+
+ //-- 4. create a files in the middle
+ for(i=0; i<KBM_Repetitions; ++i)
+ {
+ buf.Format(KFileNameMiddle, i);
+ nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
+ test_KErrNone(nRes);
+ }
+
+ //-- 5. fill second half FAT
+ for(i=nHalf1; i<KMaxFillFiles; ++i)
+ {
+ buf.Format(KFileNameFiller, i);
+ nRes = CreateEmptyFile(TheFs, buf, KFillFileSz);
+ test_KErrNone(nRes);
+ }
+
+
+ //-- 6. create files in the very end (occupiy last FAT entries)
+ for(i=0; i<KBM_Repetitions; ++i)
+ {
+ buf.Format(KFileNameLast, i);
+ nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
+ test_KErrNone(nRes);
+ }
+
+ return ETrue;
+}
+
+/**
+ Mounts and dismounts FAT volume several times calculating average time taken to mount.
+ Also can stress FS by calling stress function that can do some work on the volume.
+
+ @param apStressFN pointer to the stressing function which can be called just after mounting. Can be NULL.
+ @return time in milliseconds taken to mout the volume
+*/
+static TUint32 DoMeasureMountTime(TStressFN apStressFN)
+{
+
+ TInt nRes;
+
+ TTime timeStart;
+ TTime timeEnd;
+
+ TInt64 usMountTime=0; //-- total time taken by "Mount"
+
+ //-- disable FAT test utils print out, it can affects measured time
+ EnablePrintOutput(EFalse);
+
+ for(TInt i=0; i<KBM_Repetitions; ++i)
+ {
+
+ //-- A. remount FS taking the time when mounting starts
+ nRes = RemountFS(TheFs, gDriveNum, &timeStart);
+ test_KErrNone(nRes);
+
+ //-- B. call a given stress function
+ if(apStressFN)
+ apStressFN(i);
+
+ //-- C. take end time
+ timeEnd.UniversalTime();
+ test_KErrNone(nRes);
+
+ usMountTime += (timeEnd.MicroSecondsFrom(timeStart)).Int64();
+ }
+
+ const TUint32 msMountTime = (TUint32)usMountTime / (K1mSec*KBM_Repetitions);
+
+ EnablePrintOutput(ETrue); //-- Enable FAT test utils print out
+
+ return msMountTime;
+}
+
+//-------------------------------------------------------------------
+
+/**
+ Stress function.
+ Use case: read access to the first file on the volume in root dir.
+*/
+static void FirstReadAccess_FirstFile_Stress(TInt aRepNo)
+{
+ TBuf<64> buf;
+ buf.Format(KFileNameFirst, aRepNo);
+
+ TInt nRes = VerifyCheckableFile(TheFs, buf);
+ test_KErrNone(nRes);
+}
+
+
+/**
+ Stress function.
+ Use case: read access to the middle file on the volume in root dir.
+*/
+static void FirstReadAccess_MiddleFile_Stress(TInt aRepNo)
+{
+ TBuf<64> buf;
+ buf.Format(KFileNameMiddle, aRepNo);
+
+ TInt nRes = VerifyCheckableFile(TheFs, buf);
+ test_KErrNone(nRes);
+}
+
+/**
+ Stress function.
+ Use case: read access to the last file on the volume in root dir.
+*/
+static void FirstReadAccess_LastFile_Stress(TInt aRepNo)
+{
+ TBuf<64> buf;
+ buf.Format(KFileNameLast, aRepNo);
+
+ TInt nRes = VerifyCheckableFile(TheFs, buf);
+ test_KErrNone(nRes);
+}
+
+/**
+ Stress function.
+ Use case: Getting volume information SYNCHRONOUSLY.
+*/
+static void GetVolInfo_Synch_Stress(TInt)
+{
+ TVolumeInfo volInfo;
+ TInt nRes = TheFs.Volume(volInfo, gDriveNum);
+ test_KErrNone(nRes);
+}
+
+/**
+ Stress function.
+ Use case: Getting volume information _ASYNCHRONOUSLY_, i.e. do not wait until
+ FAT32 free space scan thread finishes
+*/
+static void GetVolInfo_Asynch_Stress(TInt)
+{
+ TVolumeInfo volInfo;
+
+ //-- let's use special version of the RFS API
+ TRequestStatus rqStat;
+ TheFs.Volume(volInfo, gDriveNum, rqStat);
+
+ User::WaitForRequest(rqStat);
+ test(rqStat.Int()==KErrNone);
+
+}
+
+//-------------------------------------------------------------------
+
+/**
+ Stress function.
+ Use case: deletes files in the beginning of the volume (or FAT table)
+*/
+static void DeleteFirstFile_Stress(TInt aRepNo)
+{
+ TBuf<64> buf;
+ buf.Format(KFileNameFirst, aRepNo);
+
+ TInt nRes = TheFs.Delete(buf);
+ test_KErrNone(nRes);
+}
+
+
+/**
+ Stress function.
+ Use case: deletes files in the middle of the volume (or FAT table)
+*/
+static void DeleteMiddleFile_Stress(TInt aRepNo)
+{
+ TBuf<64> buf;
+ buf.Format(KFileNameMiddle, aRepNo);
+
+ TInt nRes = TheFs.Delete(buf);
+ test_KErrNone(nRes);
+}
+
+/**
+ Stress function.
+ Use case: deletes files in the end of the volume (or FAT table)
+*/
+static void DeleteLastFile_Stress(TInt aRepNo)
+{
+ TBuf<64> buf;
+ buf.Format(KFileNameLast, aRepNo);
+
+ TInt nRes = TheFs.Delete(buf);
+ test_KErrNone(nRes);
+}
+
+
+//-------------------------------------------------------------------
+
+/**
+ perform series of tests that measure and print out FAT volume mount time for different secenarios
+*/
+void MeasureMountTime()
+{
+ TUint32 msTime;
+
+ if(!PrepareVolumeForBM()) //-- prepare the volume for BM tests: format it, create file structure etc.
+ return;
+
+ //-- 1. no stress function, measure just pure mount time
+ msTime = DoMeasureMountTime(NULL);
+ test.Printf(_L("#--> Pure mount:%d ms\n"), msTime);
+
+ //-- 2.1 measure mount time with a read-acess to the first file on the volume
+ msTime = DoMeasureMountTime(FirstReadAccess_FirstFile_Stress);
+ test.Printf(_L("#--> mount and read access to 1st file:%d ms\n"), msTime);
+
+ //-- 2.2 measure mount time with a read-acess to the middle file on the volume
+ msTime = DoMeasureMountTime(FirstReadAccess_MiddleFile_Stress);
+ test.Printf(_L("#--> mount and read access to middle file:%d ms\n"), msTime);
+
+ //-- 2.3 measure mount time with a read-acess to the last file on the volume
+ msTime = DoMeasureMountTime(FirstReadAccess_LastFile_Stress);
+ test.Printf(_L("#--> mount and read access to last file:%d ms\n"), msTime);
+
+ //-- 2.4 measure mount time with getting a volume information
+ msTime = DoMeasureMountTime(GetVolInfo_Synch_Stress);
+ test.Printf(_L("#--> mount and getting volInfo (synch):%d ms\n"), msTime);
+
+ msTime = DoMeasureMountTime(GetVolInfo_Asynch_Stress);
+ test.Printf(_L("#--> mount and getting volInfo (Asynch):%d ms\n"), msTime);
+
+
+ //-- 2.4 measure mount time with deleting file in the beginning (write access to the first entries of the FAT32)
+ msTime = DoMeasureMountTime(DeleteFirstFile_Stress);
+ test.Printf(_L("#--> mount and delete first file:%d ms\n"), msTime);
+
+ //-- 2.5 measure mount time with deleting file in the middle (write access to the middle entries of the FAT32)
+ msTime = DoMeasureMountTime(DeleteMiddleFile_Stress);
+ test.Printf(_L("#--> mount and delete middle file:%d ms\n"), msTime);
+
+ //-- 2.6 measure mount time with deleting file in the end (write access to the last entries of the FAT32)
+ msTime = DoMeasureMountTime(DeleteLastFile_Stress);
+ test.Printf(_L("#--> mount and delete last file:%d ms\n"), msTime);
+
+ test.Printf(_L("---\n"), msTime);
+}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID PBASE-T_MOUNT-0521
+//! @SYMTestType PT
+//! @SYMPREQ PREQ1721
+//! @SYMTestCaseDesc Testing FAT volume mount performance for various scenarios
+//!
+//! @SYMTestActions
+//! 0 Prepare the volume by formatting it and creating 100 files to occupy the space.
+//! 1 Turn OFF all mount enhancements
+//! 2 Measure and print out volume mount time for the next scenarios:
+//! a. simple mount
+//! b. mount and read access to the media (reading the last file in the root dir.)
+//! c. mount and write access to the media (writing data into the last file in the root dir)
+//! d. mount getting volume information
+//!
+//!
+//! 3 Turn ON using FSInfo.
+//! 4 Repeat step 2 for this case.
+//! @SYMTestExpectedResults Finishes ok.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+void TestFAT_Mounting_Performance()
+{
+ test.Next(_L("\n#--> Measuring FAT volumes mount performance.\n"));
+#ifndef _DEBUG
+ test.Printf(_L("Skipping the test in the Release build! \n"));
+ return;
+#else
+
+ //-- 1. turn OFF all mount enhancements like using FSInfo, backround FAT scan etc.
+ test.Printf(_L("#--> ==== All mount enhancements are disabled ====\n"));
+ SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL);
+ MeasureMountTime();
+
+ //-- 2. Turn ON using FSInfo
+ test.Printf(_L("#--> ==== Enabled Using FSInfo ====\n"));
+ SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FsInfo);
+ MeasureMountTime();
+
+ //-- 2. Turn OFF using FSInfo and ON FAT32 bacground scanning
+ test.Printf(_L("#--> ==== Enabled FAT32 BkGnd scan, FSInfo disabled ====\n"));
+ SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FatBkGndScan);
+ MeasureMountTime();
+
+ //-- restore mounting mechanism
+ SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
+
+#endif //_DEBUG
+}
+
+
+
+//-------------------------------------------------------------------
+
+/**
+ Check if the drive aDriveNo is finalised or not.
+ The "CleanShutDown" is obtained by QueryVolumeInfoExt API and by reading 2 FATs directly with checking their consistence.
+
+ @param aDriveNo drive number to query.
+ @return ETrue if the drive if finalised
+*/
+static TBool DoCheckVolumeFinalised(TInt aDriveNo)
+{
+ TInt nRes;
+ TPckgBuf<TBool> boolPckg;
+
+ //-- 1. get "Finalised" state by using the API
+ nRes = TheFs.QueryVolumeInfoExt(aDriveNo, EIsDriveFinalised, boolPckg);
+ test_KErrNone(nRes);
+
+ //-- N.B. for FAT12 the result can be either OK or "NotSupported"
+ //-- If FAT12 is in explicit "finalised" state, the result will be OK
+ //-- if not, we can't query the volume state, because FAT12 doesn't support flags in FAT[1]
+
+ const TBool bFinalised_From_API = boolPckg() >0;
+ TBool bFinalised_From_FAT1 = bFinalised_From_API;
+
+ TBuf8<32> fatBuf(32);
+ TFatBootSector bootSec;
+ const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
+
+ nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, bootSec);
+ test_KErrNone(nRes);
+
+ test(bootSec.IsValid());
+
+ const TUint32 Fat1StartPos = bootSec.FirstFatSector() * bootSec.BytesPerSector();
+
+ if(bootSec.FatType() == EFat16)
+ {//-- FAT16
+ TUint16 fatEntry;
+ const TUint16 KClnShtdnMask = 0x8000; //-- "ClnShutBitMask", see FAT specs
+
+ //-- read "CleanShutDown" flag directly from the 1st FAT
+ nRes = MediaRawRead(TheFs, gDriveNum, Fat1StartPos, fatBuf.Size(), fatBuf);
+ test_KErrNone(nRes);
+
+ Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
+ bFinalised_From_FAT1 = (fatEntry & KClnShtdnMask) >0;
+
+
+ for(TInt i=1; i<bootSec.NumberOfFats(); ++i)
+ {
+ //-- read a flag from the next FAT
+ const TUint32 currFatStartPos = (bootSec.FirstFatSector() + i*bootSec.TotalFatSectors())*bootSec.BytesPerSector();
+
+ nRes = MediaRawRead(TheFs, gDriveNum, currFatStartPos, fatBuf.Size(), fatBuf);
+ test_KErrNone(nRes);
+
+ Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
+ const TBool bFinalised_From_currFAT = (fatEntry & KClnShtdnMask)>0;
+
+ test(bFinalised_From_currFAT == bFinalised_From_FAT1);
+ }
+
+ }
+ else if(bootSec.FatType() == EFat32)
+ {//-- FAT32
+ TUint32 fatEntry;
+ const TUint32 KClnShtdnMask = 0x08000000; //-- "ClnShutBitMask", see FAT specs
+
+ //-- read "CleanShutDown" flag directly from the 1st FAT
+ nRes = MediaRawRead(TheFs, gDriveNum, Fat1StartPos, fatBuf.Size(), fatBuf);
+ test_KErrNone(nRes);
+
+ Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
+ bFinalised_From_FAT1 = (fatEntry & KClnShtdnMask) >0;
+
+ for(TInt i=1; i<bootSec.NumberOfFats(); ++i)
+ {
+ //-- read a flag from the next FAT
+ const TUint32 currFatStartPos = (bootSec.FirstFatSector() + i*bootSec.TotalFatSectors())*bootSec.BytesPerSector();
+
+ nRes = MediaRawRead(TheFs, gDriveNum, currFatStartPos, fatBuf.Size(), fatBuf);
+ test_KErrNone(nRes);
+
+ Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
+ const TBool bFinalised_From_currFAT = (fatEntry & KClnShtdnMask) >0;
+
+ test(bFinalised_From_currFAT == bFinalised_From_FAT1);
+ }
+
+ }
+ else //-- FAT12
+ {//-- FAT12 doesn't have flags in FAT[1]
+ bFinalised_From_FAT1 = bFinalised_From_API;
+ }
+
+ test(bFinalised_From_FAT1 == bFinalised_From_API);
+
+ return bFinalised_From_API;
+}
+
+
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID PBASE-T_MOUNT-0522
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1721
+//! @SYMTestCaseDesc RFs::FinaliseDrive() and RFs::FinaliseDrives() API
+//!
+//! @SYMTestActions
+//! 0 Finalise the drive in RW mode and check the result.
+//! 1 Finalise the drive in RW mode once again and check the result.
+//! 2 Create a file and check that the volume has become unfinalised.
+//! 3 Open a file, try to finalise the volume; it shall fail with KErrInUse
+//! 4 close the file, finalise, check that the result is OK.
+//! 5 "Unfinalise" the volume; check that the volume is not finalised any longer.
+//! 6 Finalise the drive in RO mode and check the result.
+//! 7 Try to create a file, shall fail with KErrAccessDenied
+//! 8 Try to finalise into RW mode, shall fail with KErrAccessDenied
+//! 9 Try to unfinalise volume, it shall remain RO
+//! 10 Remount the drive, it shall become RW and finalised
+//! 11 Test transition "Not finalised" -> EFinal_RW (expected: KErrNone)
+//! 12 Test transition EFinal_RW -> EFinal_RO (expected: KErrNone)
+//! 13 Test transition EFinal_RO -> EFinal_RW (expected: KErrAccessDenied)
+//! 14 Remount the volume to reset RO flag
+//! 15 test old RFs::FinaliseDrives() API by finalising all drives in the system
+//!
+//! @SYMTestExpectedResults finishes if the volume finalisation works correctly. panics otherwise
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+static void TestFinaliseFS()
+{
+ test.Next(_L("Testing RFs::FinaliseDrives() API\n"));
+
+ if(!Is_Fat16(TheFs, gDriveNum) && !Is_Fat32(TheFs, gDriveNum))
+ {
+ test.Printf(_L("This step requires FAT16 or FAT32 ! Skipping.\n"));
+ return;
+ }
+
+ TInt nRes;
+ TBool bDriveFinalised;
+
+ //============= 1. finalise the drive (RW mode) and check the result
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test_KErrNone(nRes);
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ //-- 1.1 finalise the drive second time EFinal_RW -> EFinal_RW shall work
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test_KErrNone(nRes);
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ //============= 2. create a file. Shall succeed (EFinal_RW), the volume shall become unfinalised
+
+ RFile file;
+ _LIT(KFileName, "\\my_file1.dat");
+
+ nRes = CreateEmptyFile(TheFs, KFileName, 128000);
+ test_KErrNone(nRes);
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(!bDriveFinalised); //-- the volume has become "unfinalised"
+
+ //-- 2.1 open a file, try to finalise; Shall dail with KErrInUse
+ nRes = file.Replace(TheFs, KFileName, EFileWrite | EFileRead);
+ test_KErrNone(nRes);
+
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test(nRes==KErrInUse); //-- can't finalise drives with opened objects
+
+ file.Close();
+
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test_KErrNone(nRes);
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ //============= 3. test "unfinalise API"
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EForceUnfinalise);
+ test_KErrNone(nRes);
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(!bDriveFinalised); //-- the volume has become "unfinalised"
+
+ //============= 4. test finalisation into RO mode
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RO); //-- the volume becomes RO
+ test_KErrNone(nRes);
+
+ //-- try to write a file on RO volume; it shall fail with KErrAccessDenied
+ nRes = CreateEmptyFile(TheFs, KFileName, 128000);
+ test(nRes == KErrAccessDenied);
+ file.Close();
+
+ //-- 4.1 try to finalise into EFinal_RW mode, shall fail with KErrAccessDenied
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test(nRes == KErrAccessDenied);
+
+ //-- 4.2 "unfinalise" the volume, it still shall remain RO
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EForceUnfinalise);
+ test_KErrNone(nRes);
+
+ //-- try to write a file on RO volume; it shall fail with KErrAccessDenied
+ nRes = CreateEmptyFile(TheFs, KFileName, 128000);
+ test(nRes == KErrAccessDenied);
+ file.Close();
+
+ //-- remount FS, the drive shall become RW
+ nRes = RemountFS(TheFs, gDriveNum);
+ test_KErrNone(nRes);
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ //-- try to write a file on RW volume, shall be OK
+ nRes = CreateEmptyFile(TheFs, KFileName, 128000);
+ test(nRes == KErrNone);
+ file.Close();
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(!bDriveFinalised);
+
+ //============= 5. test various finalisation modes
+
+ //-- 5.1 Not finalised -> EFinal_RW (KErrNone)
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test(nRes == KErrNone);
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ //-- 5.2 EFinal_RW -> EFinal_RO (KErrNone)
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RO);
+ test(nRes == KErrNone);
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ //-- 5.2 EFinal_RO -> EFinal_RW (KErrAccessDenied)
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test(nRes == KErrAccessDenied);
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ //-- 5.3 restore
+ nRes = RemountFS(TheFs, gDriveNum);
+ test_KErrNone(nRes);
+
+
+ //============= 6. test old RFs::FinaliseDrives API
+
+ nRes = CreateEmptyFile(TheFs, KFileName, 128000);
+ test(nRes == KErrNone);
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(!bDriveFinalised);
+
+ TheFs.FinaliseDrives(); //-- shall work as TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW) but for ALL drives
+
+ bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ nRes = CreateEmptyFile(TheFs, KFileName, 128000);
+ test(nRes == KErrNone);
+
+}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID PBASE-T_MOUNT-0523
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1721
+//! @SYMTestCaseDesc testing boot and backup boot sectors on FAT32 volume
+//!
+//! @SYMTestActions
+//! 0 Quick format the drive
+//! 1 read main and backup boot & fsinfo sectors and check their validity
+//! 2 corrupt main boot sector and check that the drive can be mounted (backup boot sector is used)
+//! 3 corrupt backup boot sector and check that the drive can not be mounted.
+//! 4 Quick format the drive to restore test environment
+//!
+//! @SYMTestExpectedResults finishes if the boot sector and backup boot sector functionality compliant with the FAT specs. panics otherwise
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+static void TestBackupBootSector()
+{
+ test.Next(_L("Testing Backup Boot Sector.\n"));
+
+ TInt nRes;
+
+ //-- quick format the drive
+ FormatVolume(ETrue);
+
+ if(!Is_Fat32(TheFs, gDriveNum))
+ {
+ test.Printf(_L("This step requires FAT32 ! Skipping.\n"));
+ return;
+ }
+
+ TFatBootSector mainBootSec, backupBootSec;
+ TFSInfo mainFSInfo, backupFSInfo;
+
+ const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
+ const TUint32 posBkBootSec = KBkBootSectorNum << KDefaultSectorLog2;
+
+ //-- read main and backup boot & fsinfo sectors and check their validity
+ nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, mainBootSec);
+ test_KErrNone(nRes);
+
+ //-- backup boot sector # must be 6
+ nRes = ReadBootSector(TheFs, gDriveNum, posBkBootSec, backupBootSec);
+ test_KErrNone(nRes);
+
+ test(mainBootSec.IsValid());
+ test(backupBootSec.IsValid());
+ test(mainBootSec == backupBootSec);
+
+ //-- read fsinfo sectors
+ const TUint32 posMainFSInfo = mainBootSec.FSInfoSectorNum() << KDefaultSectorLog2;
+ const TUint32 posBkFSInfo = (KBkBootSectorNum + mainBootSec.FSInfoSectorNum()) << KDefaultSectorLog2;
+
+ test(posMainFSInfo != 0);
+ test(posBkFSInfo != 0);
+
+ nRes = ReadFSInfoSector(TheFs, gDriveNum, posMainFSInfo, mainFSInfo);
+ test_KErrNone(nRes);
+
+ nRes = ReadFSInfoSector(TheFs, gDriveNum, posBkFSInfo, backupFSInfo);
+ test_KErrNone(nRes);
+
+ test(mainFSInfo.IsValid());
+ test(backupFSInfo.IsValid());
+ test(mainFSInfo == backupFSInfo);
+
+ //-- corrupt main boot sector and check that the drive can be mounted
+ test.Printf(_L("Corrupting main boot sector...\n"));
+
+
+ //-- A1. corrupt main boot sector starting from the pos:0
+ nRes = FillMedia(TheFs, gDriveNum, posMainBootSec, posMainBootSec+KDefaultSectorSize, 0xaa);
+
+ //-- A2. remount FS, it shall be OK because of the using backup boot sector
+ nRes = RemountFS(TheFs, gDriveNum);
+ test_KErrNone(nRes);
+
+
+ //-- B1. corrupt BACKUP boot sector starting from the sec:6
+ nRes = FillMedia(TheFs, gDriveNum, posBkBootSec, posBkBootSec+KDefaultSectorSize, 0xbb);
+
+ //-- B2. remount FS, unable to mount.
+ nRes = RemountFS(TheFs, gDriveNum);
+ test(nRes == KErrCorrupt);
+
+
+ //-- quick format the drive
+ FormatVolume(ETrue);
+
+}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID PBASE-T_MOUNT-0524
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1721
+//! @SYMTestCaseDesc testing FSInfo sector functionality.
+//!
+//! @SYMTestActions
+//! 0 Quick format the drive
+//! 1 finalise the drive to write correct data to the FSInfo & its backup copy.
+//! 2 read FSInfo sector, its backup copy and check that they are both valid, identical and contain correct data
+//! 3 check that after the formatting FS info values are the same as real, obtained from the FAT scanning.
+//! 4 create a random - sized file, check that after finalisation the number of free clusters is identical to the FSinfo
+//! 5 Quick format the drive to restore test environment
+//!
+//! @SYMTestExpectedResults finishes if the FSInfo sectors functionality compliant with the FAT specs. panics otherwise
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+static void TestFSInfoSector()
+{
+ test.Next(_L("Testing FSInfo Sector.\n"));
+
+#ifndef _DEBUG
+ test.Printf(_L("Skipping the test in the Release build! \n"));
+ return;
+#else
+
+ TInt nRes;
+
+ //-- quick format the drive
+ FormatVolume(ETrue);
+
+ if(!Is_Fat32(TheFs, gDriveNum))
+ {
+ test.Printf(_L("This step requires FAT32 ! Skipping.\n"));
+ return;
+ }
+
+ TFatBootSector bootSec;
+ const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
+ nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, bootSec);
+ test_KErrNone(nRes);
+
+ const TUint32 bytesPerSector = bootSec.BytesPerSector();
+ const TUint32 secPerClust = bootSec.SectorsPerCluster();
+
+ //-- finalise the drive, just in case
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test_KErrNone(nRes);
+
+ //============= 1. read FSInfo sector and its backup copy and compare them
+ TFSInfo fsInfoSec;
+
+ //-- main FSInfo
+ nRes = ReadFSInfoSector(TheFs, gDriveNum, KFSInfoSectorNum*bytesPerSector, fsInfoSec);
+ test_KErrNone(nRes);
+ test(fsInfoSec.IsValid());
+
+ TUint32 freeClusters_FSInfo = fsInfoSec.FreeClusterCount();
+ TUint32 nextFree_FSInfo = fsInfoSec.NextFreeCluster();
+
+ //-- backup FSInfo
+ nRes = ReadFSInfoSector(TheFs, gDriveNum, KBkFSInfoSectorNum*bytesPerSector, fsInfoSec);
+ test_KErrNone(nRes);
+ test(fsInfoSec.IsValid());
+
+ //-- both copies must be identical
+ test(freeClusters_FSInfo == fsInfoSec.FreeClusterCount());
+ test(nextFree_FSInfo == fsInfoSec.NextFreeCluster());
+
+ //-- FAT[0] and FAT[1] are not used; FAT[2] is taken by the 1st cluster of the FAT32 Root directory.
+ test(nextFree_FSInfo == (2+1));
+
+ //============= 2. check that after the formatting FS info values are the same as real.
+
+ //-- 2.1 disable using FSInfo and other stuff
+ SetFsyDebugFlag(gDriveNum, KMntProp_Disable_FsInfo);
+
+ //-- remount FAT; using FSInfo is disabled. FAT will be explicitly scanned.
+ nRes = RemountFS(TheFs, gDriveNum);
+ test_KErrNone(nRes);
+
+ //-- restore mounting mechanism
+ SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
+
+ //-- get free clusters number from the FSY, which in turn had counted them explicitly
+ TVolumeInfo volInfo;
+ nRes = TheFs.Volume(volInfo, gDriveNum);
+ test_KErrNone(nRes);
+
+ TUint32 freeClusters = (TUint32)(volInfo.iFree / (bytesPerSector * secPerClust));
+ test(freeClusters == freeClusters_FSInfo);
+
+ //============= 3. create a random - sized file, check that after finalisation the number of free clusters is identical to the FSinfo
+ _LIT(KFileName, "\\FILE1.DAT");
+ const TUint32 rndClusters = 7+((TUint32)Math::Rand(gRndSeed)) % 5000;
+ const TUint32 fileSz = rndClusters * bytesPerSector * secPerClust;
+ nRes = CreateEmptyFile(TheFs, KFileName, fileSz);
+ test_KErrNone(nRes);
+
+ //-- 3.1 get data from FS
+ nRes = TheFs.Volume(volInfo, gDriveNum);
+ test_KErrNone(nRes);
+ freeClusters = (TUint32)(volInfo.iFree / (bytesPerSector * secPerClust));
+
+ //-- 3.2 finalise the volume and get data from FSInfo
+ nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
+ test_KErrNone(nRes);
+
+ //-- main FSInfo
+ nRes = ReadFSInfoSector(TheFs, gDriveNum, KFSInfoSectorNum*bytesPerSector, fsInfoSec);
+ test_KErrNone(nRes);
+ test(fsInfoSec.IsValid());
+
+ freeClusters_FSInfo = fsInfoSec.FreeClusterCount();
+ nextFree_FSInfo = fsInfoSec.NextFreeCluster();
+
+ //-- backup FSInfo
+ nRes = ReadFSInfoSector(TheFs, gDriveNum, KBkFSInfoSectorNum*bytesPerSector, fsInfoSec);
+ test_KErrNone(nRes);
+ test(fsInfoSec.IsValid());
+
+ //-- both copies must be identical
+ test(freeClusters_FSInfo == fsInfoSec.FreeClusterCount());
+ test(nextFree_FSInfo == fsInfoSec.NextFreeCluster());
+
+ //-- the information in FSInfo must be the same as in FAT
+ test(freeClusters == freeClusters_FSInfo);
+
+ TBool bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
+ test(bDriveFinalised);
+
+ TheFs.Delete(KFileName);
+
+ //-- restore mounting mechanism
+ SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
+
+#endif //_DEBUG
+}
+
+//-------------------------------------------------------------------
+
+/** initialise test global objects */
+static void InitGlobals()
+{
+ TInt nRes;
+
+ //-- define a propery which will control mount process in the fsy.
+ //-- The property key is a drive number being tested
+
+ _LIT_SECURITY_POLICY_PASS(KTestPropPolicy);
+ nRes = RProperty::Define(KThisTestSID, gDriveNum, RProperty::EInt, KTestPropPolicy, KTestPropPolicy);
+ test(nRes == KErrNone || nRes == KErrAlreadyExists);
+
+ nRes = RProperty::Set(KThisTestSID, gDriveNum, KMntProp_EnableALL);
+ test_KErrNone(nRes);
+
+ gRndSeed = Math::Random();
+ (void)&gRndSeed; //-- get rid of warning
+}
+
+/** destroy test global objects */
+static void DestroyGlobals()
+{
+ //-- delete test property
+ RProperty::Delete(KThisTestSID, gDriveNum);
+
+ TVolumeInfo v;
+ TheFs.Volume(v);
+}
+
+//-------------------------------------------------------------------
+/**
+ Manual test. Requires manual removing and putting back the media.
+ On the emulator one can use pressing (and holding) F5 key to simulate media removal.
+*/
+void Manual_TestRemount_On_MediaRemoval()
+{
+ TInt nRes;
+
+ _LIT(KFileName, "\\my_file1.dat");
+ const TUint32 KFileSz = K1MegaByte;
+
+ //-- 1. create a file
+ nRes = CreateEmptyFile(TheFs, KFileName, KFileSz);
+ test_KErrNone(nRes);
+
+ RFile file;
+
+ nRes = file.Open(TheFs, KFileName, EFileRead | EFileWrite);
+ test_KErrNone(nRes);
+
+ TBuf8<512> buf(512);
+ TVolumeInfo vi;
+ buf.FillZ();
+
+ TKeyCode key;
+
+ for(;;)
+ {
+ TheFs.SetDebugRegister(0x00);
+
+ nRes = file.Read(0, buf);
+
+ test.Printf(_L("Remove the media and press a key.\n"));
+ key = test.Getch();
+ if(key == EKeyEscape)
+ break;
+
+ TheFs.SetDebugRegister(KFSYS | KFSERV);
+ nRes = file.Read(0, buf);
+
+ if(nRes != KErrNone)
+ {
+
+ test.Printf(_L("ReadFile: %d!\n"), nRes);
+
+ key = test.Getch();
+ if(key == EKeyEscape)
+ break;
+
+ nRes = TheFs.Volume(vi,gDriveNum);
+ test.Printf(_L("Volume: %d!\n"), nRes);
+
+ key = test.Getch();
+ if(key == EKeyEscape)
+ break;
+
+ nRes = file.Write(0, buf);
+ test.Printf(_L("WriteFile: %d!\n"), nRes);
+
+ key = test.Getch();
+ if(key == EKeyEscape)
+ break;
+
+ }
+
+ }
+
+
+ file.Close();
+}
+
+
+//-------------------------------------------------------------------
+/**
+ Wait for the request aRqStat to be completed with timeout.
+
+ @param aRqStat request status object we need to wait to complete
+ @param aTimeout_uS timeout in microseconds
+
+ @return ETrue if the aRqStat is completed before time is out
+ EFalse if aTimeout_uS has passed. And the state of the aRqStat not changed.
+*/
+TBool WaitForRequestWithTimeout(TRequestStatus& aRqStat, TUint32 aTimeout_uS)
+{
+ TRequestStatus rqStatTimeout(KRequestPending);
+ RTimer tmrTimeOut;
+ TInt nRes;
+ TBool bReqCompleted;
+
+ if(aRqStat.Int() != KRequestPending)
+ return ETrue; //-- nothing to wait for.
+
+ //-- set up a timeout timer
+ nRes = tmrTimeOut.CreateLocal();
+ test(nRes == KErrNone);
+
+ tmrTimeOut.After(rqStatTimeout, aTimeout_uS);
+
+ User::WaitForRequest(aRqStat, rqStatTimeout);
+
+ if(aRqStat == KRequestPending)
+ {//-- timeout.
+ bReqCompleted = EFalse;
+ }
+ else
+ {//-- the main request has been completed, cancel timer
+ bReqCompleted = ETrue;
+ if(rqStatTimeout.Int() == KRequestPending)
+ {
+ tmrTimeOut.Cancel();
+ User::WaitForRequest(rqStatTimeout);
+ }
+ }
+
+ tmrTimeOut.Close();
+
+ return bReqCompleted;
+}
+
+//-------------------------------------------------------------------
+
+void TestNotifyDiskSpace()
+{
+ test.Next(_L("Testing NotifyDiskSpace() on asynchronous mounting\n"));
+
+#ifndef _DEBUG
+ test.Printf(_L("Skipping the test in the Release build! \n"));
+ return;
+#else
+
+ TInt nRes;
+ TRequestStatus rqStat;
+ TVolumeInfo volInfo;
+
+ //-- quick format the drive
+ FormatVolume(ETrue);
+
+ if(!Is_Fat32(TheFs, gDriveNum))
+ {//-- only FAT32 supports asynch mounting;
+ test.Printf(_L("This test step requires FAT32!\n"));
+ return;
+ }
+
+ //-- FAT32 free space threshold that is supposed to be triggered by notifiers
+ const TInt64 KFreeSpaceThreshold = 300*K1MegaByte;
+
+ //-- Turn OFF using FSInfo and ON FAT32 background scanning; it will cause compulsory FAT32 background free clusters scan.
+ //-- if FAT32 background free clusters scan is disabled in config, this test can hang on waiting for free space notifications.
+ test.Printf(_L("==== Enabled FAT32 BkGnd scan, FSInfo disabled ====\n"));
+ SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FatBkGndScan);
+
+
+ //===== create a big file in the beginning in order to avoid freeSpaceThreshold being reached too fast
+ nRes = CreateEmptyFile(TheFs, _L("\\big_empty_file.bin"), 10*K1MegaByte);
+ test_KErrNone(nRes);
+
+//TheFs.SetDebugRegister(0x03);
+
+ //===== Test that FAT32 free space scanning thread updates File Server free space notifiers
+ test.Printf(_L("Testing FAT32 free space scanning thread triggers notifiers..."));
+
+ nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it must cause FAT32 free space scan in background
+ test_KErrNone(nRes);
+
+ test.Printf(_L("Waiting for %LU bytes available on the volume...\n"), KFreeSpaceThreshold);
+
+ //-- check if we can use the notifiers at all... If free space is >= KFreeSpaceThreshold, the notifier won't be triggered
+ //-- get _current_ amount of free space asynchronously
+ TheFs.Volume(volInfo, gDriveNum, rqStat);
+ User::WaitForRequest(rqStat);
+ test(rqStat.Int()==KErrNone);
+
+ if(volInfo.iSize <= KFreeSpaceThreshold)
+ {
+ test.Printf(_L("The volume is too small for %LU bytes notify ...\n"), KFreeSpaceThreshold);
+ test.Printf(_L("The test is inconclusive ...\n"));
+ return;
+ }
+
+ if(volInfo.iFree >= KFreeSpaceThreshold)
+ {
+ test.Printf(_L("The volume already has %LU free bytes...\n"), volInfo.iFree);
+ test.Printf(_L("The test is inconclusive ...\n"));
+ return;
+ }
+
+
+ TheFs.NotifyDiskSpace(KFreeSpaceThreshold, gDriveNum, rqStat);
+ test(rqStat.Int()==KRequestPending);
+
+ //-- wait for notification for 30 seconds; If for some reason FAT32 background scanning for free clusters doesn't
+ //-- work (e.g. configued out in FAT), this test is inconclusive.
+ TBool bCompleted = WaitForRequestWithTimeout(rqStat, 30*K1Sec);
+
+ if(!bCompleted)
+ {
+ test.Printf(_L("Wait timeout! something is wrong...\n"));
+ test(0);
+ }
+
+ test_KErrNone(rqStat.Int());
+
+ //-- get _current_ amount of free space asynchronously
+ TheFs.Volume(volInfo, gDriveNum, rqStat);
+ User::WaitForRequest(rqStat);
+ test(rqStat.Int()==KErrNone);
+ test.Printf(_L("Current amount of free space on the volume: %LU \n"), volInfo.iFree);
+
+
+ //===== Test that aborting FAT32 free space scanning thread will trigger notifiers
+ test.Printf(_L("Testing aborting FAT32 free space scanning thread..."));
+
+ nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it must cause FAT32 free space scan in background
+ test_KErrNone(nRes);
+
+ TheFs.NotifyDiskSpace(KFreeSpaceThreshold, gDriveNum, rqStat);
+ test(rqStat.Int()==KRequestPending);
+
+ nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it will abort the scanning thread
+ test_KErrNone(nRes);
+
+ test(rqStat.Int() != KRequestPending);
+
+ //-- get _current_ amount of free space asynchronously
+ TheFs.Volume(volInfo, gDriveNum, rqStat);
+ User::WaitForRequest(rqStat);
+ test(rqStat.Int()==KErrNone);
+ test.Printf(_L("Current amount of free space on the volume: %LU \n"), volInfo.iFree);
+
+
+ //-- find out free space on the volume; it will also blocks until FAT32 free space scanning finishes.
+ nRes = TheFs.Volume(volInfo);
+ test(nRes==KErrNone);
+ test.Printf(_L("free space on the volume: %LU \n"), volInfo.iFree);
+
+
+//TheFs.SetDebugRegister(0x00);
+
+ //-- restore mounting mechanism
+ SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
+
+#endif //_DEBUG
+}
+
+//-------------------------------------------------------------------
+
+void CallTestsL()
+ {
+ //-- set up console output
+ Fat_Test_Utils::SetConsole(test.Console());
+
+ TInt nRes=TheFs.CharToDrive(gDriveToTest, gDriveNum);
+ test(nRes==KErrNone);
+
+ //-- check if this is FAT
+ if(!Is_Fat(TheFs, gDriveNum) || Is_Automounter(TheFs, gDriveNum))
+ {//-- it doesn't make much sense to run this test under automounter+FAT. The automounter can't easily handle formatting corrupted media
+ //-- and the mounting permaormance measurements don't make much sense in this case as well.
+
+ test.Printf(_L("Skipping. This test requires explicitly mounted FAT file system.\n"));
+ return;
+ }
+
+ //-- check this is not the internal ram drive
+ TVolumeInfo v;
+
+ nRes = TheFs.Volume(v);
+ test(nRes==KErrNone);
+ if(v.iDrive.iMediaAtt & KMediaAttVariableSize)
+ {
+ test.Printf(_L("Skipping. Internal ram drive not tested.\n"));
+ return;
+ }
+
+ //-------------------------------------
+
+ PrintDrvInfo(TheFs, gDriveNum);
+ InitGlobals();
+
+
+ TestNotifyDiskSpace();
+
+ //-------------------------------------
+ TestBackupBootSector();
+ TestFSInfoSector();
+ TestFinaliseFS();
+
+ //-------------------------------------
+ TestFAT_Mounting_Performance();
+ //-------------------------------------
+ //-- manual test
+ //Manual_TestRemount_On_MediaRemoval();
+
+ //-------------------------------------
+ DestroyGlobals();
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+