kerneltest/f32test/filesystem/fat/t_mount.cpp
changeset 0 a41df078684a
child 199 189ece41fa29
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32test\server\t_mount.cpp
       
    15 // Testing some issues connected with mounting/dismounting file fystems, drives finalisation etc.
       
    16 //
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #define __E32TEST_EXTENSION__
       
    24 
       
    25 #include <f32file.h>
       
    26 #include <e32test.h>
       
    27 #include <e32math.h>
       
    28 #include <e32property.h>
       
    29 #include <f32dbg.h>
       
    30 
       
    31 #include "t_server.h"
       
    32 #include "fat_utils.h"
       
    33 
       
    34 using namespace Fat_Test_Utils;
       
    35 
       
    36 #ifdef __VC32__
       
    37     // Solve compilation problem caused by non-English locale
       
    38     #pragma setlocale("english")
       
    39 #endif
       
    40 
       
    41 RTest test(_L("T_Mount"));
       
    42 
       
    43 static TInt     gDriveNum=-1; ///< drive number we are dealing with
       
    44 static TInt64   gRndSeed;
       
    45 
       
    46 
       
    47 const TInt KBM_Repetitions = 5;     ///< number of repetitions for BM testing
       
    48 const TUint32 KCheckFileSize = 533; ///< size of the small file to be deleted
       
    49 
       
    50 _LIT(KFileNameFirst,  "\\FIRST%d.DAT");
       
    51 _LIT(KFileNameMiddle, "\\MID%d.DAT");
       
    52 _LIT(KFileNameLast,   "\\LAST%d.DAT");
       
    53 _LIT(KFileNameFiller, "\\FILL%d.DAT");
       
    54 
       
    55 typedef void (*TStressFN)(TInt);    //-- pointer to the FAT mount stress function
       
    56 
       
    57 
       
    58 //-------------------------------------------------------------------
       
    59 //-- debug bit flags that may be set in the property which controls FAT volume mounting
       
    60 
       
    61 const TUid KThisTestSID={0x10210EB3}; ///< this EXE SID
       
    62 
       
    63 const TUint32 KMntProp_EnableALL    = 0x00000000; //-- enable all operations
       
    64 
       
    65 #ifdef _DEBUG
       
    66 
       
    67 const TUint32 KMntProp_DisableALL   = 0xFFFFFFFF; //-- disable all operations
       
    68 const TUint32 KMntProp_Disable_FsInfo       = 0x00000001; //-- mask for disabling/enabling FSInfo information
       
    69 const TUint32 KMntProp_Disable_FatBkGndScan = 0x00000002; //-- mask for disabling/enabling FAT background scanner
       
    70 
       
    71 #endif
       
    72 
       
    73 //-------------------------------------------------------------------
       
    74 
       
    75 /** set a debug property value, which then wiil be read by FAT fsy */
       
    76 void SetFsyDebugFlag(TInt aDriveNo, TUint32 aFlags)
       
    77 {
       
    78     TInt nRes;
       
    79 
       
    80     nRes = RProperty::Set(KThisTestSID, aDriveNo, aFlags);
       
    81     test_KErrNone(nRes);
       
    82 }
       
    83 
       
    84 //-------------------------------------------------------------------
       
    85 /**
       
    86     format the volume and read the boot sector
       
    87 */
       
    88 static void FormatVolume(TBool aQuickFormat)
       
    89 {
       
    90     TInt nRes;
       
    91 
       
    92     #if 0
       
    93     //-- FAT32 SPC:1; for the FAT32 testing on the emulator
       
    94     (void)aQuickFormat;
       
    95 
       
    96     #ifdef  __EPOC32__
       
    97     test.Printf(_L("This is emulator configuration!!!!\n"));
       
    98     test(0);
       
    99     #endif
       
   100 
       
   101     TFatFormatParam fp;
       
   102     fp.iFatType = EFat32;
       
   103     fp.iSecPerCluster = 1;
       
   104     nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue, &fp); //-- always quick; doesn't matter for the emulator
       
   105     #else
       
   106     nRes = FormatFatDrive(TheFs, CurrentDrive(), aQuickFormat);
       
   107     #endif
       
   108 
       
   109     test_KErrNone(nRes);
       
   110 
       
   111 }
       
   112 
       
   113 //-------------------------------------------------------------------
       
   114 
       
   115 /**
       
   116     Prepare FAT volume for mounting performance testing
       
   117 
       
   118     1. quick format the drive
       
   119     2. create KBM_Repetitions files in the beginning (first files)
       
   120     3. create KMaxFillFiles/2 large files (they take about 40% of the volume);
       
   121     4. create KBM_Repetitions files (middle files)
       
   122     5. create KMaxFillFiles/2 large files (they take other 40% of the volume);
       
   123     6. create KBM_Repetitions files (last files)
       
   124 
       
   125     @return ETrue if everythis is OK
       
   126 */
       
   127 TBool PrepareVolumeForBM()
       
   128 {
       
   129     test.Printf(_L("Prepare the volume for BM testing...\n"));
       
   130 
       
   131     TInt nRes;
       
   132     TInt i;
       
   133 
       
   134     //-- 1. quick format the drive
       
   135     FormatVolume(ETrue);
       
   136 
       
   137 
       
   138     if(!Is_Fat32(TheFs, gDriveNum))
       
   139     {
       
   140         test.Printf(_L("This test requires FAT32 ! Skipping.\n"));
       
   141         return EFalse;
       
   142     }
       
   143 
       
   144     TVolumeInfo volInfo;
       
   145     nRes = TheFs.Volume(volInfo, gDriveNum);
       
   146     test_KErrNone(nRes);
       
   147 
       
   148     //-- the files will take 80% of the drive space
       
   149     const TInt    KMaxFillFiles = 100;
       
   150     const TUint32 KFillFileSz = (TUint32)((volInfo.iFree*8) / (10*KMaxFillFiles));
       
   151 
       
   152     //-- 2. create KBM_Repetitions files in the very begining (occupies first FAT entries)
       
   153     TBuf<64> buf;
       
   154 
       
   155     for(i=0; i<KBM_Repetitions; ++i)
       
   156     {
       
   157         buf.Format(KFileNameFirst, i);
       
   158         nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
       
   159         test_KErrNone(nRes);
       
   160     }
       
   161 
       
   162     //-- 3. Fill the FAT with entries and cteate a file in the middle
       
   163     const TInt nHalf1 = KMaxFillFiles / 2;
       
   164 
       
   165     for(i=0; i<nHalf1; ++i)
       
   166     {
       
   167         buf.Format(KFileNameFiller, i);
       
   168         nRes = CreateEmptyFile(TheFs, buf, KFillFileSz);
       
   169         test_KErrNone(nRes);
       
   170     }
       
   171 
       
   172     //-- 4. create a files in the middle
       
   173     for(i=0; i<KBM_Repetitions; ++i)
       
   174     {
       
   175         buf.Format(KFileNameMiddle, i);
       
   176         nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
       
   177         test_KErrNone(nRes);
       
   178     }
       
   179 
       
   180     //-- 5. fill second half FAT
       
   181     for(i=nHalf1; i<KMaxFillFiles; ++i)
       
   182     {
       
   183         buf.Format(KFileNameFiller, i);
       
   184         nRes = CreateEmptyFile(TheFs, buf, KFillFileSz);
       
   185         test_KErrNone(nRes);
       
   186     }
       
   187 
       
   188 
       
   189     //-- 6. create files in the very end (occupiy last FAT entries)
       
   190     for(i=0; i<KBM_Repetitions; ++i)
       
   191     {
       
   192         buf.Format(KFileNameLast, i);
       
   193         nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
       
   194         test_KErrNone(nRes);
       
   195     }
       
   196 
       
   197     return ETrue;
       
   198 }
       
   199 
       
   200 /**
       
   201     Mounts and dismounts FAT volume several times calculating average time taken to mount.
       
   202     Also can stress FS by calling stress function that can do some work on the volume.
       
   203 
       
   204     @param  apStressFN pointer to the stressing function which can be called just after mounting. Can be NULL.
       
   205     @return time in milliseconds taken to mout the volume
       
   206 */
       
   207 static TUint32 DoMeasureMountTime(TStressFN apStressFN)
       
   208 {
       
   209 
       
   210     TInt nRes;
       
   211 
       
   212     TTime   timeStart;
       
   213     TTime   timeEnd;
       
   214 
       
   215     TInt64   usMountTime=0;      //-- total time taken by "Mount"
       
   216 
       
   217     //-- disable FAT test utils print out, it can affects measured time
       
   218     EnablePrintOutput(EFalse);
       
   219 
       
   220     for(TInt i=0; i<KBM_Repetitions; ++i)
       
   221     {
       
   222 
       
   223         //-- A. remount FS taking the time when mounting starts
       
   224         nRes = RemountFS(TheFs, gDriveNum, &timeStart);
       
   225         test_KErrNone(nRes);
       
   226 
       
   227         //-- B. call a given stress function
       
   228         if(apStressFN)
       
   229             apStressFN(i);
       
   230 
       
   231         //-- C. take end time
       
   232         timeEnd.UniversalTime();
       
   233         test_KErrNone(nRes);
       
   234 
       
   235         usMountTime += (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   236      }
       
   237 
       
   238     const TUint32 msMountTime = (TUint32)usMountTime / (K1mSec*KBM_Repetitions);
       
   239 
       
   240     EnablePrintOutput(ETrue); //-- Enable FAT test utils print out
       
   241 
       
   242     return msMountTime;
       
   243 }
       
   244 
       
   245 //-------------------------------------------------------------------
       
   246 
       
   247 /**
       
   248     Stress function.
       
   249     Use case: read access to the first file on the volume in root dir.
       
   250 */
       
   251 static void FirstReadAccess_FirstFile_Stress(TInt aRepNo)
       
   252 {
       
   253     TBuf<64> buf;
       
   254     buf.Format(KFileNameFirst, aRepNo);
       
   255 
       
   256     TInt nRes = VerifyCheckableFile(TheFs, buf);
       
   257     test_KErrNone(nRes);
       
   258 }
       
   259 
       
   260 
       
   261 /**
       
   262     Stress function.
       
   263     Use case: read access to the middle file on the volume in root dir.
       
   264 */
       
   265 static void FirstReadAccess_MiddleFile_Stress(TInt aRepNo)
       
   266 {
       
   267     TBuf<64> buf;
       
   268     buf.Format(KFileNameMiddle, aRepNo);
       
   269 
       
   270     TInt nRes = VerifyCheckableFile(TheFs, buf);
       
   271     test_KErrNone(nRes);
       
   272 }
       
   273 
       
   274 /**
       
   275     Stress function.
       
   276     Use case: read access to the last file on the volume in root dir.
       
   277 */
       
   278 static void FirstReadAccess_LastFile_Stress(TInt aRepNo)
       
   279 {
       
   280     TBuf<64> buf;
       
   281     buf.Format(KFileNameLast, aRepNo);
       
   282 
       
   283     TInt nRes = VerifyCheckableFile(TheFs, buf);
       
   284     test_KErrNone(nRes);
       
   285 }
       
   286 
       
   287 /**
       
   288     Stress function.
       
   289     Use case: Getting volume information SYNCHRONOUSLY.
       
   290 */
       
   291 static void GetVolInfo_Synch_Stress(TInt)
       
   292 {
       
   293     TVolumeInfo volInfo;
       
   294     TInt nRes = TheFs.Volume(volInfo, gDriveNum);
       
   295     test_KErrNone(nRes);
       
   296 }
       
   297 
       
   298 /**
       
   299     Stress function.
       
   300     Use case: Getting volume information _ASYNCHRONOUSLY_, i.e. do not wait until
       
   301     FAT32 free space scan thread finishes
       
   302 */
       
   303 static void GetVolInfo_Asynch_Stress(TInt)
       
   304 {
       
   305     TVolumeInfo volInfo;
       
   306 
       
   307     //-- let's use special version of the RFS API
       
   308     TRequestStatus rqStat;
       
   309     TheFs.Volume(volInfo, gDriveNum, rqStat);
       
   310 
       
   311     User::WaitForRequest(rqStat);
       
   312     test(rqStat.Int()==KErrNone);
       
   313 
       
   314 }
       
   315 
       
   316 //-------------------------------------------------------------------
       
   317 
       
   318 /**
       
   319     Stress function.
       
   320     Use case: deletes files in the beginning of the volume (or FAT table)
       
   321 */
       
   322 static void DeleteFirstFile_Stress(TInt aRepNo)
       
   323 {
       
   324     TBuf<64> buf;
       
   325     buf.Format(KFileNameFirst, aRepNo);
       
   326 
       
   327     TInt nRes = TheFs.Delete(buf);
       
   328     test_KErrNone(nRes);
       
   329 }
       
   330 
       
   331 
       
   332 /**
       
   333     Stress function.
       
   334     Use case: deletes files in the middle of the volume (or FAT table)
       
   335 */
       
   336 static void DeleteMiddleFile_Stress(TInt aRepNo)
       
   337 {
       
   338     TBuf<64> buf;
       
   339     buf.Format(KFileNameMiddle, aRepNo);
       
   340 
       
   341     TInt nRes = TheFs.Delete(buf);
       
   342     test_KErrNone(nRes);
       
   343 }
       
   344 
       
   345 /**
       
   346     Stress function.
       
   347     Use case: deletes files in the end of the volume (or FAT table)
       
   348 */
       
   349 static void DeleteLastFile_Stress(TInt aRepNo)
       
   350 {
       
   351     TBuf<64> buf;
       
   352     buf.Format(KFileNameLast, aRepNo);
       
   353 
       
   354     TInt nRes = TheFs.Delete(buf);
       
   355     test_KErrNone(nRes);
       
   356 }
       
   357 
       
   358 
       
   359 //-------------------------------------------------------------------
       
   360 
       
   361 /**
       
   362     perform series of tests that measure and print out FAT volume mount time for different secenarios
       
   363 */
       
   364 void MeasureMountTime()
       
   365 {
       
   366     TUint32 msTime;
       
   367 
       
   368     if(!PrepareVolumeForBM()) //-- prepare the volume for BM tests: format it, create file structure etc.
       
   369         return;
       
   370 
       
   371     //-- 1. no stress function, measure just pure mount time
       
   372     msTime = DoMeasureMountTime(NULL);
       
   373     test.Printf(_L("#--> Pure mount:%d ms\n"), msTime);
       
   374 
       
   375     //-- 2.1 measure mount time with a read-acess to the first file on the volume
       
   376     msTime = DoMeasureMountTime(FirstReadAccess_FirstFile_Stress);
       
   377     test.Printf(_L("#--> mount and read access to 1st file:%d ms\n"), msTime);
       
   378 
       
   379     //-- 2.2 measure mount time with a read-acess to the middle file on the volume
       
   380     msTime = DoMeasureMountTime(FirstReadAccess_MiddleFile_Stress);
       
   381     test.Printf(_L("#--> mount and read access to middle file:%d ms\n"), msTime);
       
   382 
       
   383     //-- 2.3 measure mount time with a read-acess to the last file on the volume
       
   384     msTime = DoMeasureMountTime(FirstReadAccess_LastFile_Stress);
       
   385     test.Printf(_L("#--> mount and read access to last file:%d ms\n"), msTime);
       
   386 
       
   387     //-- 2.4 measure mount time with getting a volume information
       
   388     msTime = DoMeasureMountTime(GetVolInfo_Synch_Stress);
       
   389     test.Printf(_L("#--> mount and getting volInfo (synch):%d ms\n"), msTime);
       
   390 
       
   391     msTime = DoMeasureMountTime(GetVolInfo_Asynch_Stress);
       
   392     test.Printf(_L("#--> mount and getting volInfo (Asynch):%d ms\n"), msTime);
       
   393 
       
   394 
       
   395     //-- 2.4 measure mount time with deleting file in the beginning (write access to the first entries of the FAT32)
       
   396     msTime = DoMeasureMountTime(DeleteFirstFile_Stress);
       
   397     test.Printf(_L("#--> mount and delete first file:%d ms\n"), msTime);
       
   398 
       
   399     //-- 2.5 measure mount time with deleting file in the middle (write access to the middle entries of the FAT32)
       
   400     msTime = DoMeasureMountTime(DeleteMiddleFile_Stress);
       
   401     test.Printf(_L("#--> mount and delete middle file:%d ms\n"), msTime);
       
   402 
       
   403     //-- 2.6 measure mount time with deleting file in the end (write access to the last entries of the FAT32)
       
   404     msTime = DoMeasureMountTime(DeleteLastFile_Stress);
       
   405     test.Printf(_L("#--> mount and delete last file:%d ms\n"), msTime);
       
   406 
       
   407     test.Printf(_L("---\n"), msTime);
       
   408 }
       
   409 
       
   410 //----------------------------------------------------------------------------------------------
       
   411 //! @SYMTestCaseID      PBASE-T_MOUNT-0521
       
   412 //! @SYMTestType        PT
       
   413 //! @SYMPREQ            PREQ1721
       
   414 //! @SYMTestCaseDesc    Testing FAT volume mount performance for various scenarios
       
   415 //!
       
   416 //! @SYMTestActions
       
   417 //!             0   Prepare the volume by formatting it and creating 100 files to occupy the space.
       
   418 //!             1   Turn OFF all mount enhancements
       
   419 //!             2   Measure and print out volume mount time for the next scenarios:
       
   420 //!                   a.  simple mount
       
   421 //!                   b.  mount and read access to the media (reading the last file in the root dir.)
       
   422 //!                   c.  mount and write access to the media (writing data into the last file in the root dir)
       
   423 //!                   d.  mount getting volume information
       
   424 //!
       
   425 //!
       
   426 //!             3     Turn ON using FSInfo.
       
   427 //!             4     Repeat step 2 for this case.
       
   428 //! @SYMTestExpectedResults Finishes ok.
       
   429 //! @SYMTestPriority        High
       
   430 //! @SYMTestStatus          Implemented
       
   431 //----------------------------------------------------------------------------------------------
       
   432 void TestFAT_Mounting_Performance()
       
   433 {
       
   434     test.Next(_L("\n#--> Measuring FAT volumes mount performance.\n"));
       
   435 #ifndef _DEBUG
       
   436     test.Printf(_L("Skipping the test in the Release build! \n"));
       
   437     return;
       
   438 #else
       
   439 
       
   440    //-- 1. turn OFF all mount enhancements like using FSInfo, backround FAT scan etc.
       
   441    test.Printf(_L("#--> ==== All mount enhancements are disabled ====\n"));
       
   442    SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL);
       
   443    MeasureMountTime();
       
   444 
       
   445    //-- 2. Turn ON using FSInfo
       
   446    test.Printf(_L("#--> ==== Enabled Using FSInfo ====\n"));
       
   447    SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FsInfo);
       
   448    MeasureMountTime();
       
   449 
       
   450    //-- 2. Turn OFF using FSInfo and ON FAT32 bacground scanning
       
   451    test.Printf(_L("#--> ==== Enabled FAT32 BkGnd scan, FSInfo disabled ====\n"));
       
   452    SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FatBkGndScan);
       
   453    MeasureMountTime();
       
   454 
       
   455    //-- restore mounting mechanism
       
   456    SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
       
   457 
       
   458 #endif //_DEBUG
       
   459 }
       
   460 
       
   461 
       
   462 
       
   463 //-------------------------------------------------------------------
       
   464 
       
   465 /**
       
   466     Check if the drive aDriveNo is finalised or not.
       
   467     The "CleanShutDown" is obtained by QueryVolumeInfoExt API and by reading 2 FATs directly with checking their consistence.
       
   468 
       
   469     @param  aDriveNo drive number to query.
       
   470     @return ETrue if the drive if finalised
       
   471 */
       
   472 static TBool DoCheckVolumeFinalised(TInt aDriveNo)
       
   473 {
       
   474     TInt nRes;
       
   475     TPckgBuf<TBool> boolPckg;
       
   476 
       
   477     //-- 1. get "Finalised" state by using the API
       
   478     nRes = TheFs.QueryVolumeInfoExt(aDriveNo, EIsDriveFinalised, boolPckg);
       
   479     test_KErrNone(nRes);
       
   480 
       
   481     //-- N.B. for FAT12 the result can be either OK or "NotSupported"
       
   482     //-- If FAT12 is in explicit "finalised" state, the result will be OK
       
   483     //-- if not, we can't query the volume state, because FAT12 doesn't support flags in FAT[1]
       
   484 
       
   485     const TBool bFinalised_From_API = boolPckg() >0;
       
   486           TBool bFinalised_From_FAT1 = bFinalised_From_API;
       
   487 
       
   488     TBuf8<32> fatBuf(32);
       
   489     TFatBootSector  bootSec;
       
   490     const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
       
   491 
       
   492     nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, bootSec);
       
   493     test_KErrNone(nRes);
       
   494 
       
   495     test(bootSec.IsValid());
       
   496 
       
   497     const TUint32 Fat1StartPos = bootSec.FirstFatSector() * bootSec.BytesPerSector();
       
   498 
       
   499     if(bootSec.FatType() == EFat16)
       
   500     {//-- FAT16
       
   501         TUint16 fatEntry;
       
   502         const TUint16 KClnShtdnMask = 0x8000; //-- "ClnShutBitMask", see FAT specs
       
   503 
       
   504         //-- read "CleanShutDown" flag directly from the 1st FAT
       
   505         nRes = MediaRawRead(TheFs, gDriveNum, Fat1StartPos, fatBuf.Size(), fatBuf);
       
   506         test_KErrNone(nRes);
       
   507 
       
   508         Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
       
   509         bFinalised_From_FAT1 = (fatEntry & KClnShtdnMask) >0;
       
   510 
       
   511 
       
   512         for(TInt i=1; i<bootSec.NumberOfFats(); ++i)
       
   513         {
       
   514             //-- read a flag from the next FAT
       
   515             const TUint32 currFatStartPos = (bootSec.FirstFatSector() + i*bootSec.TotalFatSectors())*bootSec.BytesPerSector();
       
   516 
       
   517             nRes = MediaRawRead(TheFs, gDriveNum, currFatStartPos, fatBuf.Size(), fatBuf);
       
   518             test_KErrNone(nRes);
       
   519 
       
   520             Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
       
   521             const TBool bFinalised_From_currFAT = (fatEntry & KClnShtdnMask)>0;
       
   522 
       
   523             test(bFinalised_From_currFAT == bFinalised_From_FAT1);
       
   524         }
       
   525 
       
   526     }
       
   527     else if(bootSec.FatType() == EFat32)
       
   528     {//-- FAT32
       
   529         TUint32 fatEntry;
       
   530         const TUint32 KClnShtdnMask = 0x08000000; //-- "ClnShutBitMask", see FAT specs
       
   531 
       
   532         //-- read "CleanShutDown" flag directly from the 1st FAT
       
   533         nRes = MediaRawRead(TheFs, gDriveNum, Fat1StartPos, fatBuf.Size(), fatBuf);
       
   534         test_KErrNone(nRes);
       
   535 
       
   536         Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
       
   537         bFinalised_From_FAT1 = (fatEntry & KClnShtdnMask) >0;
       
   538 
       
   539         for(TInt i=1; i<bootSec.NumberOfFats(); ++i)
       
   540         {
       
   541             //-- read a flag from the next FAT
       
   542             const TUint32 currFatStartPos = (bootSec.FirstFatSector() + i*bootSec.TotalFatSectors())*bootSec.BytesPerSector();
       
   543 
       
   544             nRes = MediaRawRead(TheFs, gDriveNum, currFatStartPos, fatBuf.Size(), fatBuf);
       
   545             test_KErrNone(nRes);
       
   546 
       
   547             Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
       
   548             const TBool bFinalised_From_currFAT = (fatEntry & KClnShtdnMask) >0;
       
   549 
       
   550             test(bFinalised_From_currFAT == bFinalised_From_FAT1);
       
   551         }
       
   552 
       
   553     }
       
   554     else  //-- FAT12
       
   555     {//-- FAT12 doesn't have flags in FAT[1]
       
   556      bFinalised_From_FAT1 = bFinalised_From_API;
       
   557     }
       
   558 
       
   559     test(bFinalised_From_FAT1 == bFinalised_From_API);
       
   560 
       
   561     return bFinalised_From_API;
       
   562 }
       
   563 
       
   564 
       
   565 
       
   566 //----------------------------------------------------------------------------------------------
       
   567 //! @SYMTestCaseID      PBASE-T_MOUNT-0522
       
   568 //! @SYMTestType        UT
       
   569 //! @SYMPREQ            PREQ1721
       
   570 //! @SYMTestCaseDesc    RFs::FinaliseDrive() and RFs::FinaliseDrives() API
       
   571 //!
       
   572 //! @SYMTestActions
       
   573 //!             0   Finalise the drive in RW mode and check the result.
       
   574 //!             1   Finalise the drive in RW mode once again and check the result.
       
   575 //!             2   Create a file and check that the volume has become unfinalised.
       
   576 //!             3   Open a file, try to finalise the volume; it shall fail with KErrInUse
       
   577 //!             4   close the file, finalise, check that the result is OK.
       
   578 //!             5   "Unfinalise" the volume; check that the volume is not finalised any longer.
       
   579 //!             6   Finalise the drive in RO mode and check the result.
       
   580 //!             7   Try to create a file, shall fail with KErrAccessDenied
       
   581 //!             8   Try to finalise into RW mode, shall fail with KErrAccessDenied
       
   582 //!             9   Try to unfinalise volume, it shall remain RO
       
   583 //!             10  Remount the drive, it shall become RW and finalised
       
   584 //!             11  Test transition "Not finalised" -> EFinal_RW (expected: KErrNone)
       
   585 //!             12  Test transition EFinal_RW -> EFinal_RO  (expected: KErrNone)
       
   586 //!             13  Test transition EFinal_RO -> EFinal_RW  (expected: KErrAccessDenied)
       
   587 //!             14  Remount the volume to reset RO flag
       
   588 //!             15  test old RFs::FinaliseDrives() API by finalising all drives in the system
       
   589 //!
       
   590 //! @SYMTestExpectedResults finishes if the volume finalisation works correctly. panics otherwise
       
   591 //! @SYMTestPriority        High
       
   592 //! @SYMTestStatus          Implemented
       
   593 //----------------------------------------------------------------------------------------------
       
   594 static void TestFinaliseFS()
       
   595 {
       
   596     test.Next(_L("Testing RFs::FinaliseDrives() API\n"));
       
   597 
       
   598     if(!Is_Fat16(TheFs, gDriveNum) && !Is_Fat32(TheFs, gDriveNum))
       
   599     {
       
   600         test.Printf(_L("This step requires FAT16 or FAT32 ! Skipping.\n"));
       
   601         return;
       
   602     }
       
   603 
       
   604     TInt  nRes;
       
   605     TBool bDriveFinalised;
       
   606 
       
   607     //============= 1. finalise the drive (RW mode) and check the result
       
   608     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   609     test_KErrNone(nRes);
       
   610 
       
   611     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   612     test(bDriveFinalised);
       
   613 
       
   614     //-- 1.1 finalise the drive second time EFinal_RW -> EFinal_RW shall work
       
   615     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   616     test_KErrNone(nRes);
       
   617 
       
   618     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   619     test(bDriveFinalised);
       
   620 
       
   621     //============= 2. create a file. Shall succeed (EFinal_RW), the volume shall become unfinalised
       
   622 
       
   623     RFile file;
       
   624     _LIT(KFileName, "\\my_file1.dat");
       
   625 
       
   626     nRes = CreateEmptyFile(TheFs, KFileName, 128000);
       
   627     test_KErrNone(nRes);
       
   628 
       
   629     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   630     test(!bDriveFinalised); //-- the volume has become "unfinalised"
       
   631 
       
   632     //-- 2.1 open a file, try to finalise; Shall dail with KErrInUse
       
   633     nRes = file.Replace(TheFs, KFileName, EFileWrite | EFileRead);
       
   634     test_KErrNone(nRes);
       
   635 
       
   636     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   637     test(nRes==KErrInUse); //-- can't finalise drives with opened objects
       
   638 
       
   639     file.Close();
       
   640 
       
   641     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   642     test_KErrNone(nRes);
       
   643 
       
   644     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   645     test(bDriveFinalised);
       
   646 
       
   647     //============= 3. test "unfinalise API"
       
   648     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EForceUnfinalise);
       
   649     test_KErrNone(nRes);
       
   650 
       
   651     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   652     test(!bDriveFinalised); //-- the volume has become "unfinalised"
       
   653 
       
   654     //============= 4. test finalisation into RO mode
       
   655     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RO); //-- the volume becomes RO
       
   656     test_KErrNone(nRes);
       
   657 
       
   658     //-- try to write a file on RO volume; it shall fail with KErrAccessDenied
       
   659     nRes = CreateEmptyFile(TheFs, KFileName, 128000);
       
   660     test(nRes == KErrAccessDenied);
       
   661     file.Close();
       
   662 
       
   663     //-- 4.1 try to finalise into EFinal_RW mode, shall fail with KErrAccessDenied
       
   664     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   665     test(nRes == KErrAccessDenied);
       
   666 
       
   667     //-- 4.2 "unfinalise" the volume, it still shall remain RO
       
   668     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EForceUnfinalise);
       
   669     test_KErrNone(nRes);
       
   670 
       
   671     //-- try to write a file on RO volume; it shall fail with KErrAccessDenied
       
   672     nRes = CreateEmptyFile(TheFs, KFileName, 128000);
       
   673     test(nRes == KErrAccessDenied);
       
   674     file.Close();
       
   675 
       
   676     //-- remount FS, the drive shall become RW
       
   677     nRes = RemountFS(TheFs, gDriveNum);
       
   678     test_KErrNone(nRes);
       
   679 
       
   680     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   681     test(bDriveFinalised);
       
   682 
       
   683     //-- try to write a file on RW volume, shall be OK
       
   684     nRes = CreateEmptyFile(TheFs, KFileName, 128000);
       
   685     test(nRes == KErrNone);
       
   686     file.Close();
       
   687 
       
   688     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   689     test(!bDriveFinalised);
       
   690 
       
   691     //============= 5. test various finalisation modes
       
   692 
       
   693     //-- 5.1  Not finalised -> EFinal_RW (KErrNone)
       
   694     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   695     test(nRes == KErrNone);
       
   696     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   697     test(bDriveFinalised);
       
   698 
       
   699     //-- 5.2  EFinal_RW -> EFinal_RO (KErrNone)
       
   700     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RO);
       
   701     test(nRes == KErrNone);
       
   702     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   703     test(bDriveFinalised);
       
   704 
       
   705     //-- 5.2  EFinal_RO -> EFinal_RW  (KErrAccessDenied)
       
   706     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   707     test(nRes == KErrAccessDenied);
       
   708     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   709     test(bDriveFinalised);
       
   710 
       
   711     //-- 5.3 restore
       
   712     nRes = RemountFS(TheFs, gDriveNum);
       
   713     test_KErrNone(nRes);
       
   714 
       
   715 
       
   716     //============= 6. test old RFs::FinaliseDrives API
       
   717 
       
   718     nRes = CreateEmptyFile(TheFs, KFileName, 128000);
       
   719     test(nRes == KErrNone);
       
   720 
       
   721     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   722     test(!bDriveFinalised);
       
   723 
       
   724     TheFs.FinaliseDrives(); //-- shall work as TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW) but for ALL drives
       
   725 
       
   726     bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   727     test(bDriveFinalised);
       
   728 
       
   729     nRes = CreateEmptyFile(TheFs, KFileName, 128000);
       
   730     test(nRes == KErrNone);
       
   731 
       
   732 }
       
   733 
       
   734 //----------------------------------------------------------------------------------------------
       
   735 //! @SYMTestCaseID      PBASE-T_MOUNT-0523
       
   736 //! @SYMTestType        UT
       
   737 //! @SYMPREQ            PREQ1721
       
   738 //! @SYMTestCaseDesc    testing boot and backup boot sectors on FAT32 volume
       
   739 //!
       
   740 //! @SYMTestActions
       
   741 //!             0   Quick format the drive
       
   742 //!             1   read main and backup boot & fsinfo sectors and check their validity
       
   743 //!             2   corrupt main boot sector and check that the drive can be mounted (backup boot sector is used)
       
   744 //!             3   corrupt backup boot sector and check that the drive can not be mounted.
       
   745 //!             4   Quick format the drive to restore test environment
       
   746 //!
       
   747 //! @SYMTestExpectedResults finishes if the boot sector and backup boot sector functionality compliant with the FAT specs. panics otherwise
       
   748 //! @SYMTestPriority        High
       
   749 //! @SYMTestStatus          Implemented
       
   750 //----------------------------------------------------------------------------------------------
       
   751 static void TestBackupBootSector()
       
   752 {
       
   753     test.Next(_L("Testing Backup Boot Sector.\n"));
       
   754 
       
   755     TInt nRes;
       
   756 
       
   757     //-- quick format the drive
       
   758     FormatVolume(ETrue);
       
   759 
       
   760     if(!Is_Fat32(TheFs, gDriveNum))
       
   761     {
       
   762         test.Printf(_L("This step requires FAT32 ! Skipping.\n"));
       
   763         return;
       
   764     }
       
   765 
       
   766     TFatBootSector  mainBootSec, backupBootSec;
       
   767     TFSInfo         mainFSInfo, backupFSInfo;
       
   768 
       
   769     const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
       
   770     const TUint32 posBkBootSec   = KBkBootSectorNum << KDefaultSectorLog2;
       
   771 
       
   772     //-- read main and backup boot & fsinfo sectors and check their validity
       
   773     nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, mainBootSec);
       
   774     test_KErrNone(nRes);
       
   775 
       
   776     //-- backup boot sector # must be 6
       
   777     nRes = ReadBootSector(TheFs, gDriveNum, posBkBootSec, backupBootSec);
       
   778     test_KErrNone(nRes);
       
   779 
       
   780     test(mainBootSec.IsValid());
       
   781     test(backupBootSec.IsValid());
       
   782     test(mainBootSec == backupBootSec);
       
   783 
       
   784     //-- read fsinfo sectors
       
   785     const TUint32 posMainFSInfo = mainBootSec.FSInfoSectorNum() << KDefaultSectorLog2;
       
   786     const TUint32 posBkFSInfo   = (KBkBootSectorNum + mainBootSec.FSInfoSectorNum()) << KDefaultSectorLog2;
       
   787 
       
   788     test(posMainFSInfo != 0);
       
   789     test(posBkFSInfo != 0);
       
   790 
       
   791     nRes = ReadFSInfoSector(TheFs, gDriveNum, posMainFSInfo, mainFSInfo);
       
   792     test_KErrNone(nRes);
       
   793 
       
   794     nRes = ReadFSInfoSector(TheFs, gDriveNum, posBkFSInfo, backupFSInfo);
       
   795     test_KErrNone(nRes);
       
   796 
       
   797     test(mainFSInfo.IsValid());
       
   798     test(backupFSInfo.IsValid());
       
   799     test(mainFSInfo == backupFSInfo);
       
   800 
       
   801     //-- corrupt main boot sector and check that the drive can be mounted
       
   802     test.Printf(_L("Corrupting main boot sector...\n"));
       
   803 
       
   804 
       
   805     //-- A1. corrupt main boot sector starting from the pos:0
       
   806     nRes = FillMedia(TheFs, gDriveNum, posMainBootSec, posMainBootSec+KDefaultSectorSize, 0xaa);
       
   807 
       
   808     //-- A2. remount FS, it shall be OK because of the using backup boot sector
       
   809     nRes = RemountFS(TheFs, gDriveNum);
       
   810     test_KErrNone(nRes);
       
   811 
       
   812 
       
   813     //-- B1. corrupt BACKUP boot sector starting from the sec:6
       
   814     nRes = FillMedia(TheFs, gDriveNum, posBkBootSec, posBkBootSec+KDefaultSectorSize, 0xbb);
       
   815 
       
   816     //-- B2. remount FS, unable to mount.
       
   817     nRes = RemountFS(TheFs, gDriveNum);
       
   818     test(nRes == KErrCorrupt);
       
   819 
       
   820 
       
   821     //-- quick format the drive
       
   822     FormatVolume(ETrue);
       
   823 
       
   824 }
       
   825 
       
   826 //----------------------------------------------------------------------------------------------
       
   827 //! @SYMTestCaseID      PBASE-T_MOUNT-0524
       
   828 //! @SYMTestType        UT
       
   829 //! @SYMPREQ            PREQ1721
       
   830 //! @SYMTestCaseDesc    testing FSInfo sector functionality.
       
   831 //!
       
   832 //! @SYMTestActions
       
   833 //!             0   Quick format the drive
       
   834 //!             1   finalise the drive to write correct data to the FSInfo & its backup copy.
       
   835 //!             2   read FSInfo sector, its backup copy and check that they are both valid, identical and contain correct data
       
   836 //!             3   check that after the formatting FS info values are the same as real, obtained from the FAT scanning.
       
   837 //!             4   create a random - sized file, check that after finalisation the number of free clusters is identical to the FSinfo
       
   838 //!             5   Quick format the drive to restore test environment
       
   839 //!
       
   840 //! @SYMTestExpectedResults finishes if the FSInfo sectors functionality compliant with the FAT specs. panics otherwise
       
   841 //! @SYMTestPriority        High
       
   842 //! @SYMTestStatus          Implemented
       
   843 //----------------------------------------------------------------------------------------------
       
   844 static void TestFSInfoSector()
       
   845 {
       
   846     test.Next(_L("Testing FSInfo Sector.\n"));
       
   847 
       
   848 #ifndef _DEBUG
       
   849     test.Printf(_L("Skipping the test in the Release build! \n"));
       
   850     return;
       
   851 #else
       
   852 
       
   853     TInt nRes;
       
   854 
       
   855     //-- quick format the drive
       
   856     FormatVolume(ETrue);
       
   857 
       
   858     if(!Is_Fat32(TheFs, gDriveNum))
       
   859     {
       
   860         test.Printf(_L("This step requires FAT32 ! Skipping.\n"));
       
   861         return;
       
   862     }
       
   863 
       
   864     TFatBootSector  bootSec;
       
   865     const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
       
   866     nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, bootSec);
       
   867     test_KErrNone(nRes);
       
   868 
       
   869     const TUint32 bytesPerSector = bootSec.BytesPerSector();
       
   870     const TUint32 secPerClust = bootSec.SectorsPerCluster();
       
   871 
       
   872     //-- finalise the drive, just in case
       
   873     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   874     test_KErrNone(nRes);
       
   875 
       
   876     //============= 1. read FSInfo sector and its backup copy and compare them
       
   877     TFSInfo fsInfoSec;
       
   878 
       
   879     //-- main FSInfo
       
   880     nRes = ReadFSInfoSector(TheFs, gDriveNum, KFSInfoSectorNum*bytesPerSector, fsInfoSec);
       
   881     test_KErrNone(nRes);
       
   882     test(fsInfoSec.IsValid());
       
   883 
       
   884     TUint32 freeClusters_FSInfo = fsInfoSec.FreeClusterCount();
       
   885     TUint32 nextFree_FSInfo = fsInfoSec.NextFreeCluster();
       
   886 
       
   887     //-- backup FSInfo
       
   888     nRes = ReadFSInfoSector(TheFs, gDriveNum, KBkFSInfoSectorNum*bytesPerSector, fsInfoSec);
       
   889     test_KErrNone(nRes);
       
   890     test(fsInfoSec.IsValid());
       
   891 
       
   892     //-- both copies must be identical
       
   893     test(freeClusters_FSInfo == fsInfoSec.FreeClusterCount());
       
   894     test(nextFree_FSInfo == fsInfoSec.NextFreeCluster());
       
   895 
       
   896     //-- FAT[0] and FAT[1] are not used; FAT[2] is taken by the 1st cluster of the FAT32 Root directory.
       
   897     test(nextFree_FSInfo == (2+1));
       
   898 
       
   899     //============= 2. check that after the formatting FS info values are the same as real.
       
   900 
       
   901     //-- 2.1 disable using FSInfo and other stuff
       
   902     SetFsyDebugFlag(gDriveNum, KMntProp_Disable_FsInfo);
       
   903 
       
   904     //-- remount FAT; using FSInfo is disabled. FAT will be explicitly scanned.
       
   905     nRes = RemountFS(TheFs, gDriveNum);
       
   906     test_KErrNone(nRes);
       
   907 
       
   908     //-- restore mounting mechanism
       
   909     SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
       
   910 
       
   911     //-- get free clusters number from the FSY, which in turn had counted them explicitly
       
   912     TVolumeInfo volInfo;
       
   913     nRes = TheFs.Volume(volInfo, gDriveNum);
       
   914     test_KErrNone(nRes);
       
   915 
       
   916     TUint32 freeClusters = (TUint32)(volInfo.iFree / (bytesPerSector * secPerClust));
       
   917     test(freeClusters == freeClusters_FSInfo);
       
   918 
       
   919     //============= 3. create a random - sized file, check that after finalisation the number of free clusters is identical to the FSinfo
       
   920     _LIT(KFileName, "\\FILE1.DAT");
       
   921     const TUint32 rndClusters = 7+((TUint32)Math::Rand(gRndSeed)) % 5000;
       
   922     const TUint32 fileSz = rndClusters * bytesPerSector * secPerClust;
       
   923     nRes = CreateEmptyFile(TheFs, KFileName, fileSz);
       
   924     test_KErrNone(nRes);
       
   925 
       
   926     //-- 3.1 get data from FS
       
   927     nRes = TheFs.Volume(volInfo, gDriveNum);
       
   928     test_KErrNone(nRes);
       
   929     freeClusters = (TUint32)(volInfo.iFree / (bytesPerSector * secPerClust));
       
   930 
       
   931     //-- 3.2 finalise the volume and get data from FSInfo
       
   932     nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
       
   933     test_KErrNone(nRes);
       
   934 
       
   935     //-- main FSInfo
       
   936     nRes = ReadFSInfoSector(TheFs, gDriveNum, KFSInfoSectorNum*bytesPerSector, fsInfoSec);
       
   937     test_KErrNone(nRes);
       
   938     test(fsInfoSec.IsValid());
       
   939 
       
   940     freeClusters_FSInfo = fsInfoSec.FreeClusterCount();
       
   941     nextFree_FSInfo = fsInfoSec.NextFreeCluster();
       
   942 
       
   943     //-- backup FSInfo
       
   944     nRes = ReadFSInfoSector(TheFs, gDriveNum, KBkFSInfoSectorNum*bytesPerSector, fsInfoSec);
       
   945     test_KErrNone(nRes);
       
   946     test(fsInfoSec.IsValid());
       
   947 
       
   948     //-- both copies must be identical
       
   949     test(freeClusters_FSInfo == fsInfoSec.FreeClusterCount());
       
   950     test(nextFree_FSInfo == fsInfoSec.NextFreeCluster());
       
   951 
       
   952     //-- the information in FSInfo must be the same as in FAT
       
   953     test(freeClusters == freeClusters_FSInfo);
       
   954 
       
   955     TBool bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
       
   956     test(bDriveFinalised);
       
   957 
       
   958     TheFs.Delete(KFileName);
       
   959 
       
   960     //-- restore mounting mechanism
       
   961     SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
       
   962 
       
   963 #endif //_DEBUG
       
   964 }
       
   965 
       
   966 //-------------------------------------------------------------------
       
   967 
       
   968 /** initialise test global objects */
       
   969 static void InitGlobals()
       
   970 {
       
   971     TInt nRes;
       
   972 
       
   973     //-- define a propery which will control mount process in the fsy.
       
   974     //-- The property key is a drive number being tested
       
   975 
       
   976     _LIT_SECURITY_POLICY_PASS(KTestPropPolicy);
       
   977     nRes = RProperty::Define(KThisTestSID, gDriveNum, RProperty::EInt, KTestPropPolicy, KTestPropPolicy);
       
   978     test(nRes == KErrNone || nRes == KErrAlreadyExists);
       
   979 
       
   980     nRes = RProperty::Set(KThisTestSID, gDriveNum, KMntProp_EnableALL);
       
   981     test_KErrNone(nRes);
       
   982 
       
   983     gRndSeed = Math::Random();
       
   984     (void)&gRndSeed; //-- get rid of warning
       
   985 }
       
   986 
       
   987 /** destroy test global objects */
       
   988 static void DestroyGlobals()
       
   989 {
       
   990     //-- delete test property
       
   991     RProperty::Delete(KThisTestSID, gDriveNum);
       
   992 
       
   993     TVolumeInfo v;
       
   994     TheFs.Volume(v);
       
   995 }
       
   996 
       
   997 //-------------------------------------------------------------------
       
   998 /**
       
   999     Manual test. Requires manual removing and putting back the media.
       
  1000     On the emulator one can use pressing (and holding) F5 key to simulate media removal.
       
  1001 */
       
  1002 void Manual_TestRemount_On_MediaRemoval()
       
  1003 {
       
  1004     TInt nRes;
       
  1005 
       
  1006     _LIT(KFileName, "\\my_file1.dat");
       
  1007     const TUint32 KFileSz = K1MegaByte;
       
  1008 
       
  1009     //-- 1. create a file
       
  1010     nRes = CreateEmptyFile(TheFs, KFileName, KFileSz);
       
  1011     test_KErrNone(nRes);
       
  1012 
       
  1013     RFile file;
       
  1014 
       
  1015     nRes = file.Open(TheFs, KFileName, EFileRead | EFileWrite);
       
  1016     test_KErrNone(nRes);
       
  1017 
       
  1018     TBuf8<512> buf(512);
       
  1019     TVolumeInfo vi;
       
  1020     buf.FillZ();
       
  1021 
       
  1022     TKeyCode key;
       
  1023 
       
  1024     for(;;)
       
  1025     {
       
  1026         TheFs.SetDebugRegister(0x00);
       
  1027 
       
  1028         nRes = file.Read(0, buf);
       
  1029 
       
  1030         test.Printf(_L("Remove the media and press a key.\n"));
       
  1031         key = test.Getch();
       
  1032         if(key == EKeyEscape)
       
  1033                 break;
       
  1034 
       
  1035         TheFs.SetDebugRegister(KFSYS | KFSERV);
       
  1036         nRes = file.Read(0, buf);
       
  1037 
       
  1038         if(nRes != KErrNone)
       
  1039         {
       
  1040 
       
  1041             test.Printf(_L("ReadFile: %d!\n"), nRes);
       
  1042 
       
  1043             key = test.Getch();
       
  1044             if(key == EKeyEscape)
       
  1045                 break;
       
  1046 
       
  1047             nRes = TheFs.Volume(vi,gDriveNum);
       
  1048             test.Printf(_L("Volume: %d!\n"), nRes);
       
  1049 
       
  1050             key = test.Getch();
       
  1051             if(key == EKeyEscape)
       
  1052                 break;
       
  1053 
       
  1054             nRes = file.Write(0, buf);
       
  1055             test.Printf(_L("WriteFile: %d!\n"), nRes);
       
  1056 
       
  1057             key = test.Getch();
       
  1058             if(key == EKeyEscape)
       
  1059                 break;
       
  1060 
       
  1061         }
       
  1062 
       
  1063     }
       
  1064 
       
  1065 
       
  1066     file.Close();
       
  1067 }
       
  1068 
       
  1069 
       
  1070 //-------------------------------------------------------------------
       
  1071 /**
       
  1072     Wait for the request aRqStat to be completed with timeout.
       
  1073 
       
  1074     @param  aRqStat         request status object we need to wait to complete
       
  1075     @param  aTimeout_uS     timeout in microseconds
       
  1076 
       
  1077     @return ETrue   if the aRqStat is completed before time is out
       
  1078             EFalse  if aTimeout_uS has passed. And the state of the aRqStat not changed.
       
  1079 */
       
  1080 TBool WaitForRequestWithTimeout(TRequestStatus& aRqStat, TUint32 aTimeout_uS)
       
  1081 {
       
  1082     TRequestStatus  rqStatTimeout(KRequestPending);
       
  1083     RTimer          tmrTimeOut;
       
  1084     TInt            nRes;
       
  1085     TBool           bReqCompleted;
       
  1086 
       
  1087     if(aRqStat.Int() != KRequestPending)
       
  1088         return ETrue; //-- nothing to wait for.
       
  1089 
       
  1090     //-- set up a timeout timer
       
  1091     nRes = tmrTimeOut.CreateLocal();
       
  1092     test(nRes == KErrNone);
       
  1093 
       
  1094     tmrTimeOut.After(rqStatTimeout, aTimeout_uS);
       
  1095 
       
  1096     User::WaitForRequest(aRqStat, rqStatTimeout);
       
  1097 
       
  1098     if(aRqStat == KRequestPending)
       
  1099         {//-- timeout.
       
  1100         bReqCompleted = EFalse;
       
  1101         }
       
  1102         else
       
  1103         {//-- the main request has been completed, cancel timer
       
  1104             bReqCompleted = ETrue;
       
  1105             if(rqStatTimeout.Int() == KRequestPending)
       
  1106                 {
       
  1107                 tmrTimeOut.Cancel();
       
  1108                 User::WaitForRequest(rqStatTimeout);
       
  1109                 }
       
  1110         }
       
  1111 
       
  1112     tmrTimeOut.Close();
       
  1113 
       
  1114     return bReqCompleted;
       
  1115 }
       
  1116 
       
  1117 //-------------------------------------------------------------------
       
  1118 
       
  1119 void TestNotifyDiskSpace()
       
  1120 {
       
  1121     test.Next(_L("Testing NotifyDiskSpace() on asynchronous mounting\n"));
       
  1122 
       
  1123 #ifndef _DEBUG
       
  1124     test.Printf(_L("Skipping the test in the Release build! \n"));
       
  1125     return;
       
  1126 #else
       
  1127 
       
  1128     TInt nRes;
       
  1129     TRequestStatus rqStat;
       
  1130     TVolumeInfo volInfo;
       
  1131 
       
  1132     //-- quick format the drive
       
  1133     FormatVolume(ETrue);
       
  1134 
       
  1135     if(!Is_Fat32(TheFs, gDriveNum))
       
  1136     {//-- only FAT32 supports asynch mounting;
       
  1137         test.Printf(_L("This test step requires FAT32!\n"));
       
  1138         return;
       
  1139     }
       
  1140 
       
  1141     //-- FAT32 free space threshold that is supposed to be triggered by notifiers
       
  1142     const TInt64 KFreeSpaceThreshold = 300*K1MegaByte;
       
  1143 
       
  1144     //-- Turn OFF using FSInfo and ON FAT32 background scanning; it will cause compulsory FAT32 background free clusters scan.
       
  1145     //-- if FAT32 background free clusters scan is disabled in config, this test can hang on waiting for free space notifications.
       
  1146     test.Printf(_L("==== Enabled FAT32 BkGnd scan, FSInfo disabled ====\n"));
       
  1147     SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FatBkGndScan);
       
  1148 
       
  1149 
       
  1150     //===== create a big file in the beginning in order to avoid freeSpaceThreshold being reached too fast
       
  1151     nRes = CreateEmptyFile(TheFs, _L("\\big_empty_file.bin"), 10*K1MegaByte);
       
  1152     test_KErrNone(nRes);
       
  1153 
       
  1154 //TheFs.SetDebugRegister(0x03);
       
  1155 
       
  1156     //===== Test that FAT32 free space scanning thread updates File Server free space notifiers
       
  1157     test.Printf(_L("Testing FAT32 free space scanning thread triggers notifiers..."));
       
  1158 
       
  1159     nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it must cause FAT32 free space scan in background
       
  1160     test_KErrNone(nRes);
       
  1161 
       
  1162     test.Printf(_L("Waiting for %LU bytes available on the volume...\n"), KFreeSpaceThreshold);
       
  1163 
       
  1164     //-- check if we can use the notifiers at all... If free space is >= KFreeSpaceThreshold, the notifier won't be triggered
       
  1165     //-- get _current_ amount of free space asynchronously
       
  1166     TheFs.Volume(volInfo, gDriveNum, rqStat);
       
  1167     User::WaitForRequest(rqStat);
       
  1168     test(rqStat.Int()==KErrNone);
       
  1169 
       
  1170     if(volInfo.iSize <= KFreeSpaceThreshold)
       
  1171     {
       
  1172     test.Printf(_L("The volume is too small for %LU bytes notify ...\n"), KFreeSpaceThreshold);
       
  1173     test.Printf(_L("The test is inconclusive ...\n"));
       
  1174     return;
       
  1175     }
       
  1176 
       
  1177     if(volInfo.iFree >= KFreeSpaceThreshold)
       
  1178     {
       
  1179     test.Printf(_L("The volume already has %LU free bytes...\n"), volInfo.iFree);
       
  1180     test.Printf(_L("The test is inconclusive ...\n"));
       
  1181     return;
       
  1182     }
       
  1183 
       
  1184 
       
  1185     TheFs.NotifyDiskSpace(KFreeSpaceThreshold, gDriveNum, rqStat);
       
  1186     test(rqStat.Int()==KRequestPending);
       
  1187 
       
  1188     //-- wait for notification for 30 seconds; If for some reason FAT32 background scanning for free clusters doesn't
       
  1189     //-- work (e.g. configued out in FAT), this test is inconclusive.
       
  1190     TBool bCompleted = WaitForRequestWithTimeout(rqStat, 30*K1Sec);
       
  1191 
       
  1192     if(!bCompleted)
       
  1193     {
       
  1194         test.Printf(_L("Wait timeout! something is wrong...\n"));
       
  1195         test(0);
       
  1196     }
       
  1197 
       
  1198     test_KErrNone(rqStat.Int());
       
  1199 
       
  1200     //-- get _current_ amount of free space asynchronously
       
  1201     TheFs.Volume(volInfo, gDriveNum, rqStat);
       
  1202     User::WaitForRequest(rqStat);
       
  1203     test(rqStat.Int()==KErrNone);
       
  1204     test.Printf(_L("Current amount of free space on the volume: %LU \n"), volInfo.iFree);
       
  1205 
       
  1206 
       
  1207     //===== Test that aborting FAT32 free space scanning thread will trigger notifiers
       
  1208     test.Printf(_L("Testing aborting FAT32 free space scanning thread..."));
       
  1209 
       
  1210     nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it must cause FAT32 free space scan in background
       
  1211     test_KErrNone(nRes);
       
  1212 
       
  1213     TheFs.NotifyDiskSpace(KFreeSpaceThreshold, gDriveNum, rqStat);
       
  1214     test(rqStat.Int()==KRequestPending);
       
  1215 
       
  1216     nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it will abort the scanning thread
       
  1217     test_KErrNone(nRes);
       
  1218 
       
  1219     test(rqStat.Int() != KRequestPending);
       
  1220 
       
  1221     //-- get _current_ amount of free space asynchronously
       
  1222     TheFs.Volume(volInfo, gDriveNum, rqStat);
       
  1223     User::WaitForRequest(rqStat);
       
  1224     test(rqStat.Int()==KErrNone);
       
  1225     test.Printf(_L("Current amount of free space on the volume: %LU \n"), volInfo.iFree);
       
  1226 
       
  1227 
       
  1228     //-- find out free space on the volume; it will also blocks until FAT32 free space scanning finishes.
       
  1229     nRes = TheFs.Volume(volInfo);
       
  1230     test(nRes==KErrNone);
       
  1231     test.Printf(_L("free space on the volume: %LU \n"), volInfo.iFree);
       
  1232 
       
  1233 
       
  1234 //TheFs.SetDebugRegister(0x00);
       
  1235 
       
  1236     //-- restore mounting mechanism
       
  1237     SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
       
  1238 
       
  1239 #endif  //_DEBUG
       
  1240 }
       
  1241 
       
  1242 //-------------------------------------------------------------------
       
  1243 
       
  1244 void CallTestsL()
       
  1245     {
       
  1246     //-- set up console output
       
  1247     Fat_Test_Utils::SetConsole(test.Console());
       
  1248 
       
  1249     TInt nRes=TheFs.CharToDrive(gDriveToTest, gDriveNum);
       
  1250     test(nRes==KErrNone);
       
  1251 
       
  1252     //-- check if this is FAT
       
  1253     if(!Is_Fat(TheFs, gDriveNum) || Is_Automounter(TheFs, gDriveNum))
       
  1254     {//-- it doesn't make much sense to run this test under automounter+FAT. The automounter can't easily handle formatting corrupted media
       
  1255      //-- and the mounting permaormance measurements don't make much sense in this case as well.
       
  1256 
       
  1257         test.Printf(_L("Skipping. This test requires explicitly mounted FAT file system.\n"));
       
  1258         return;
       
  1259     }
       
  1260 
       
  1261     //-- check this is not the internal ram drive
       
  1262     TVolumeInfo v;
       
  1263 
       
  1264     nRes = TheFs.Volume(v);
       
  1265     test(nRes==KErrNone);
       
  1266     if(v.iDrive.iMediaAtt & KMediaAttVariableSize)
       
  1267         {
       
  1268         test.Printf(_L("Skipping. Internal ram drive not tested.\n"));
       
  1269         return;
       
  1270         }
       
  1271 
       
  1272     //-------------------------------------
       
  1273 
       
  1274     PrintDrvInfo(TheFs, gDriveNum);
       
  1275     InitGlobals();
       
  1276 
       
  1277 
       
  1278     TestNotifyDiskSpace();
       
  1279 
       
  1280     //-------------------------------------
       
  1281     TestBackupBootSector();
       
  1282     TestFSInfoSector();
       
  1283     TestFinaliseFS();
       
  1284 
       
  1285     //-------------------------------------
       
  1286     TestFAT_Mounting_Performance();
       
  1287     //-------------------------------------
       
  1288     //-- manual test
       
  1289     //Manual_TestRemount_On_MediaRemoval();
       
  1290 
       
  1291     //-------------------------------------
       
  1292     DestroyGlobals();
       
  1293 
       
  1294     }
       
  1295 
       
  1296 
       
  1297 
       
  1298 
       
  1299 
       
  1300 
       
  1301 
       
  1302 
       
  1303 
       
  1304 
       
  1305 
       
  1306 
       
  1307 
       
  1308 
       
  1309 
       
  1310 
       
  1311 
       
  1312