kerneltest/f32test/filesystem/fat/t_fatcache_bm.cpp
changeset 0 a41df078684a
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 FAT cache performance
       
    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 
       
    30 #include "t_server.h"
       
    31 //#include "t_std.h"
       
    32 
       
    33 #include "fat_utils.h"
       
    34 
       
    35 using namespace Fat_Test_Utils;
       
    36 
       
    37 #ifdef __VC32__
       
    38     // Solve compilation problem caused by non-English locale
       
    39     #pragma setlocale("english")
       
    40 #endif
       
    41 
       
    42 RTest test(_L("T_FAT_Cache_BM"));
       
    43 
       
    44 //-- note that this test disables all FAT mount enhancements, like asynchronous mounting and using FSInfo sector.
       
    45 
       
    46 static void WaitForFatBkGndActivityEnd();
       
    47 
       
    48 //-------------------------------------------------------------------
       
    49 //-- debug bit flags that may be set in the property which controls FAT volume mounting
       
    50 
       
    51 const TUid KThisTestSID={0x10210EB3}; ///< this EXE SID
       
    52 
       
    53 //const TUint32 KMntProp_EnableALL    = 0x00000000; //-- enable all operations
       
    54 const TUint32 KMntProp_DisableALL   = 0xFFFFFFFF; //-- disable all operations
       
    55 
       
    56 //const TUint32 KMntProp_Disable_FsInfo       = 0x00000001; //-- mask for disabling/enabling FSInfo information
       
    57 //const TUint32 KMntProp_Disable_FatBkGndScan = 0x00000002; //-- mask for disabling/enabling FAT background scanner
       
    58 
       
    59 //-------------------------------------------------------------------
       
    60 
       
    61 static TInt     gDriveNum=-1; ///< drive number we are dealing with
       
    62 static TInt64   gRndSeed;
       
    63 static TFatBootSector gBootSector;
       
    64 
       
    65 static void DoRemountFS(TInt aDrive);
       
    66 
       
    67 //-- Array of integer file tars. Tags are used to identify files (the file name is generated by KFnTemplate template)
       
    68 typedef CArrayFixFlat<TInt> CFileTagsArray;
       
    69 static CFileTagsArray *pFTagArray = NULL;
       
    70 
       
    71 
       
    72 //-------------------------------------------------------------------
       
    73 const TInt KMaxFiles = 1000; //-- maximal number of files to create
       
    74 
       
    75 //-- number of unfragmented files that will be left, other files will be merged to bigger ones.
       
    76 const TInt KUnfragmentedFilesLeave = KMaxFiles/10;
       
    77 
       
    78 _LIT(KDirName, "\\DIR1\\");  //-- directory name we a working with (FAT12/16 won't allow KMaxFiles in the root dir.)
       
    79 _LIT(KFirstFileName, "\\First_file_1.nul"); //-- the name of the first file on the volume
       
    80 
       
    81 //-------------------------------------------------------------------
       
    82 
       
    83 /**
       
    84     Make a file name by its numeric tag
       
    85     @param aDes here will be a file name
       
    86     @param aFileNameTag numeric tag for the file name generation
       
    87 
       
    88 */
       
    89 void MakeFileName(TDes& aDes, TInt aFileNameTag)
       
    90 {
       
    91     _LIT(KFnTemplate, "F%d.NUL");//-- file name template, use 8.3 names here in order not to stress dir. cache much.
       
    92     aDes.Copy(KDirName);
       
    93     aDes.AppendFormat(KFnTemplate, aFileNameTag);
       
    94 }
       
    95 
       
    96 //-------------------------------------------------------------------
       
    97 /**
       
    98     format the volume and read the boot sector
       
    99 */
       
   100 static void FormatVolume(TBool aQuickFormat)
       
   101 {
       
   102     (void)aQuickFormat;
       
   103 
       
   104     #ifndef  __EPOC32__
       
   105     test.Printf(_L("This is emulator configuration!!!!\n"));
       
   106 
       
   107     //-- FAT32 SPC:1; for the FAT32 testing on the emulator
       
   108     //TFatFormatParam fp;
       
   109     //fp.iFatType = EFat32;
       
   110     //fp.iSecPerCluster = 1;
       
   111     //FormatFatDrive(TheFs, CurrentDrive(), ETrue, &fp); //-- always quick; doesn't matter for the emulator
       
   112 
       
   113     aQuickFormat = ETrue;
       
   114     #endif
       
   115 
       
   116 
       
   117     FormatFatDrive(TheFs, CurrentDrive(), aQuickFormat);
       
   118 
       
   119 
       
   120     TInt nRes = ReadBootSector(TheFs, gDriveNum, 0x00, gBootSector);
       
   121     test_KErrNone(nRes);
       
   122 }
       
   123 
       
   124 
       
   125 //-------------------------------------------------------------------
       
   126 
       
   127 /**
       
   128     Helper method. Does one iteration of merging test files into one fragmented one.
       
   129     See DoMergeFiles()
       
   130 
       
   131     @param  aFTagArray  reference to the file tags array
       
   132     @param  aBigFileNo  a sequential number of the result file to be merged from random number of smaller ones (names are taken from the tag array)
       
   133     @param  aTimeTaken_us  on return will contain time taken to this operation, in microseconds
       
   134 
       
   135     @return number of files merged into one.
       
   136 */
       
   137 TInt DoMergeTestFiles(CFileTagsArray& aFTagArray, TInt aBigFileNo, TInt64&  aTimeTaken_us)
       
   138 {
       
   139 
       
   140     aTimeTaken_us = 0;
       
   141     TTime   timeStart;
       
   142     TTime   timeEnd;
       
   143 
       
   144 
       
   145     //-- merged files' names start with this number
       
   146     const TInt KMergedFileFnThreshold = 20000;
       
   147 
       
   148     const TInt KMaxMergedFiles = 20;
       
   149     const TInt nFilesToMerge = Max((Math::Rand(gRndSeed) % KMaxMergedFiles), 2); //-- how many files to merge into one
       
   150 
       
   151     test(aFTagArray.Count() > KMaxMergedFiles);
       
   152 
       
   153     TInt selectedFTags[KMaxMergedFiles]; //-- here we will store file tags to be merged to one large fragmented file
       
   154     TInt i;
       
   155     TInt nRes;
       
   156 
       
   157     i=0;
       
   158     do
       
   159     {
       
   160         //-- randomly select a file tag from the global array
       
   161         const TInt index = (TUint)Math::Rand(gRndSeed) % aFTagArray.Count();
       
   162         const TInt fnTag = aFTagArray[index];
       
   163 
       
   164         if(fnTag < 0 || //-- no such file, already deleted
       
   165            fnTag >= KMergedFileFnThreshold) //-- this is a big, already merged file
       
   166            continue;
       
   167 
       
   168 
       
   169         selectedFTags[i] = fnTag;
       
   170         aFTagArray.Delete(index);
       
   171 
       
   172         ++i;
       
   173     }while(i<nFilesToMerge);
       
   174 
       
   175     //-- here we have file tags in selectedFNumbers array. delete these files and create one big file
       
   176     //-- with the equal size. This file will be perfectly fragmented.
       
   177     //-- search for FAT entries had priority to the right, so delete files in reverse order.
       
   178 
       
   179     TUint32 newFileSize = 0;
       
   180     TBuf<128> buf;
       
   181     RFile file;
       
   182 
       
   183     timeStart.UniversalTime(); //-- take start time
       
   184 
       
   185     for(i=0; i<nFilesToMerge; ++i)
       
   186     {
       
   187         MakeFileName(buf, selectedFTags[nFilesToMerge-1-i]);
       
   188 
       
   189         nRes=file.Open(TheFs, buf, EFileRead);
       
   190         test_KErrNone(nRes);
       
   191 
       
   192         TInt nSize;
       
   193         nRes = file.Size(nSize);
       
   194         test_KErrNone(nRes);
       
   195         file.Close();
       
   196 
       
   197         newFileSize+=(TUint32)nSize; //-- this will be the size of the new file
       
   198 
       
   199         //-- delete small file
       
   200         nRes = TheFs.Delete(buf);
       
   201         test_KErrNone(nRes);
       
   202 
       
   203     }
       
   204 
       
   205     //-- create a large file taking the place of few smaller. It will be framented.
       
   206     const TInt bigFileTag = aBigFileNo+KMergedFileFnThreshold;
       
   207 
       
   208     MakeFileName(buf, bigFileTag);
       
   209     nRes = CreateEmptyFile(TheFs, buf, newFileSize);
       
   210     test_KErrNone(nRes);
       
   211 
       
   212     timeEnd.UniversalTime(); //-- take end time
       
   213     aTimeTaken_us = (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   214 
       
   215     //-- put new big file name tag to the global array in order not to forget it for later use.
       
   216     aFTagArray.AppendL(bigFileTag);
       
   217 
       
   218     return nFilesToMerge;
       
   219 }
       
   220 
       
   221 //----------------------------------------------------------------------------------------------
       
   222 //! @SYMTestCaseID      PBASE-T_FATCACHE_BM-0689
       
   223 //! @SYMTestType        PT
       
   224 //! @SYMPREQ            PREQ1721
       
   225 //! @SYMTestCaseDesc    randomly deletes small files and creates larger. Measures time taken by this FAT fragmentation
       
   226 //!
       
   227 //! @SYMTestActions
       
   228 //!                     0   delete a random number of small files
       
   229 //!                     1   create a random number of larger files, measure time taken
       
   230 //!
       
   231 //! @SYMTestExpectedResults successful files deletion/creation
       
   232 //! @SYMTestPriority        High
       
   233 //! @SYMTestStatus          Implemented
       
   234 //----------------------------------------------------------------------------------------------
       
   235 
       
   236 /**
       
   237     precondition: We have a lot of (KMaxFiles) files of the same size on the volume. They occupy almost all FAT.
       
   238     This method randomly selects several files on the volume, deletes them and creates a bigger file that occupies space from the
       
   239     deleted files. So that we got a fragmented big file. Repeat this until we have KUnfragmentedFilesLeave initial files left on the
       
   240     volume.
       
   241 */
       
   242 void DoMergeFiles(CFileTagsArray& aFTagArray)
       
   243 {
       
   244     test.Next(_L("Merging small files to larger creating FAT fragmentation...\n"));
       
   245 
       
   246     TInt64  usTotalTime=0;
       
   247     TInt64  usCurrTime;
       
   248 
       
   249     TInt nUnfragmentedLeft = aFTagArray.Count();
       
   250     for(TInt i=0; nUnfragmentedLeft > KUnfragmentedFilesLeave; ++i)
       
   251     {
       
   252         nUnfragmentedLeft -= DoMergeTestFiles(aFTagArray, i, usCurrTime);
       
   253         usTotalTime += usCurrTime;
       
   254     }
       
   255 
       
   256     test.Printf(_L("#--> Merging files :%d ms\n"), (TUint32)usTotalTime/K1mSec);
       
   257 }
       
   258 
       
   259 //-------------------------------------------------------------------
       
   260 /**
       
   261     Randomly shuffles entries in file name tags array.
       
   262 */
       
   263 void ShuffleArray(CFileTagsArray& aFTagArray)
       
   264 {
       
   265     const TInt KSwapIterations = 500;
       
   266     const TInt arrSize = aFTagArray.Count();
       
   267 
       
   268 
       
   269     for(TInt i = 0; i<KSwapIterations; ++i)
       
   270     {//-- randomly swap 2 elements in the array
       
   271         const TInt idx1 = (TUint)Math::Rand(gRndSeed) % arrSize;
       
   272         const TInt idx2 = (TUint)Math::Rand(gRndSeed) % arrSize;
       
   273 
       
   274         TInt tmp = aFTagArray[idx1];
       
   275         aFTagArray[idx1] = aFTagArray[idx2];;
       
   276         aFTagArray[idx2] = tmp;
       
   277     }
       
   278 
       
   279 }
       
   280 
       
   281 //----------------------------------------------------------------------------------------------
       
   282 //! @SYMTestCaseID      PBASE-T_FATCACHE_BM-0690
       
   283 //! @SYMTestType        PT
       
   284 //! @SYMPREQ            PREQ1721
       
   285 //! @SYMTestCaseDesc    Measure open and seek time for all files that have tags in aFTagArray.
       
   286 //!
       
   287 //! @SYMTestActions
       
   288 //!                     0   remount FS
       
   289 //!                     1   open all files, that have tags in aFTagArray, measure time taken
       
   290 //!                     2   seek to the each file end, measure time taken
       
   291 //!
       
   292 //! @SYMTestExpectedResults successful files open/seek
       
   293 //! @SYMTestPriority        High
       
   294 //! @SYMTestStatus          Implemented
       
   295 //----------------------------------------------------------------------------------------------
       
   296 void MeasureSeekTime(CFileTagsArray& aFTagArray)
       
   297 {
       
   298     test.Next(_L("Measuring seek time...\n"));
       
   299 
       
   300     TInt nRes;
       
   301     RFile file;
       
   302     TBuf<128> buf;
       
   303 
       
   304     TTime   timeStart;
       
   305     TTime   timeEnd;
       
   306     TInt64  usTotalTimeSeek=0;
       
   307     TInt64  usTotalTimeOpen=0;
       
   308 
       
   309     const TInt KNumRepetitions = 10;
       
   310 
       
   311     for(TInt repCnt=0; repCnt<KNumRepetitions; ++repCnt)
       
   312     {
       
   313         //-- remount file system, reset caches
       
   314         DoRemountFS(gDriveNum);
       
   315 
       
   316         for(TInt i = 0; i<aFTagArray.Count(); ++i)
       
   317         {
       
   318             MakeFileName(buf, aFTagArray[i]);
       
   319 
       
   320             //-- 1. open the file
       
   321             timeStart.UniversalTime(); //-- take start time
       
   322 
       
   323                 nRes = file.Open(TheFs, buf, EFileRead);
       
   324 
       
   325             timeEnd.UniversalTime(); //-- take end time
       
   326             usTotalTimeOpen += (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   327 
       
   328             test_KErrNone(nRes);
       
   329 
       
   330 
       
   331             //-- 2. goto the end of the file. This operation shall traverse whole file's cluster chain in FAT
       
   332             timeStart.UniversalTime(); //-- take start time
       
   333 
       
   334                 TInt seekPos = 0;
       
   335                 nRes = file.Seek(ESeekEnd, seekPos);
       
   336 
       
   337             timeEnd.UniversalTime(); //-- take end time
       
   338             usTotalTimeSeek += (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   339 
       
   340             test_KErrNone(nRes);
       
   341             file.Close();
       
   342         }
       
   343     }
       
   344 
       
   345     test.Printf(_L("#--> Total open time for %d files is %d ms\n"), aFTagArray.Count(), (TUint32)usTotalTimeOpen/(K1mSec*KNumRepetitions));
       
   346     test.Printf(_L("#--> Total seek time for %d files is %d ms\n"), aFTagArray.Count(), (TUint32)usTotalTimeSeek/(K1mSec*KNumRepetitions));
       
   347 }
       
   348 
       
   349 
       
   350 //----------------------------------------------------------------------------------------------
       
   351 //! @SYMTestCaseID      PBASE-T_FATCACHE_BM-0692
       
   352 //! @SYMTestType        PT
       
   353 //! @SYMPREQ            PREQ1721
       
   354 //! @SYMTestCaseDesc    Detetes all files that have name tags in name tags array and measures time taken.
       
   355 //!
       
   356 //! @SYMTestActions
       
   357 //!                     0   remount the FS
       
   358 //!                     1   delete files and measure time taken.
       
   359 //!
       
   360 //! @SYMTestExpectedResults successful creating files
       
   361 //! @SYMTestPriority        High
       
   362 //! @SYMTestStatus          Implemented
       
   363 //----------------------------------------------------------------------------------------------
       
   364 void DeleteAllFiles(CFileTagsArray& aFTagArray)
       
   365 {
       
   366     TInt nRes;
       
   367     TBuf<128> buf;
       
   368 
       
   369     TTime   timeStart;
       
   370     TTime   timeEnd;
       
   371     TInt64  usTotalTime=0;
       
   372 
       
   373     test.Next(_L("Deleting all files...\n"));
       
   374 
       
   375     //-- remount file system, reset caches
       
   376     DoRemountFS(gDriveNum);
       
   377 
       
   378     for(TInt i = 0; i<aFTagArray.Count(); ++i)
       
   379     {
       
   380         MakeFileName(buf, aFTagArray[i]);
       
   381 
       
   382         timeStart.UniversalTime(); //-- take start time
       
   383 
       
   384         nRes = TheFs.Delete(buf);
       
   385 
       
   386         timeEnd.UniversalTime(); //-- take end time
       
   387         usTotalTime += (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   388 
       
   389         test_KErrNone(nRes);
       
   390     }
       
   391 
       
   392     test.Printf(_L("#--> Deleted %d files in %d ms\n"), aFTagArray.Count(), (TUint32)usTotalTime/K1mSec);
       
   393 }
       
   394 
       
   395 //----------------------------------------------------------------------------------------------
       
   396 //! @SYMTestCaseID      PBASE-T_FATCACHE_BM-0687
       
   397 //! @SYMTestType        PT
       
   398 //! @SYMPREQ            PREQ1721
       
   399 //! @SYMTestCaseDesc    Create KMaxFiles files to fill in space in FAT table and measure time taken.
       
   400 //!
       
   401 //! @SYMTestActions
       
   402 //!                     0   Create KMaxFiles files and measure time taken.
       
   403 //!
       
   404 //! @SYMTestExpectedResults successful creating files
       
   405 //! @SYMTestPriority        High
       
   406 //! @SYMTestStatus          Implemented
       
   407 //----------------------------------------------------------------------------------------------
       
   408 /**
       
   409     Create KMaxFiles files to fill in space in FAT table and measure time taken.
       
   410     @return EFalse if it is impossible to create test files
       
   411 */
       
   412 TBool DoCreateFiles(CFileTagsArray& aFTagArray)
       
   413 {
       
   414     TInt nRes;
       
   415     TBuf<128> buf;
       
   416 
       
   417     TTime   timeStart;
       
   418     TTime   timeEnd;
       
   419     TInt64  usTotalTime=0;
       
   420 
       
   421     test.Next(_L("Creating many files\n"));
       
   422     test.Printf(_L("Number of files:%d\n"), KMaxFiles);
       
   423 
       
   424     aFTagArray.Reset();
       
   425 
       
   426     TVolumeInfo volInfo;
       
   427     nRes = TheFs.Volume(volInfo, gDriveNum);
       
   428     test_KErrNone(nRes);
       
   429 
       
   430 
       
   431     test(gBootSector.IsValid());
       
   432 
       
   433     const TUint32 clustSz = gBootSector.SectorsPerCluster() * gBootSector.BytesPerSector();
       
   434     const TUint32 maxClusters = (TUint32)(volInfo.iFree / clustSz);
       
   435 
       
   436     if(KMaxFiles > 0.8 * maxClusters)
       
   437     {
       
   438         test.Printf(_L("Can't create %d files; skipping the test!\n"), KMaxFiles);
       
   439         return EFalse;
       
   440     }
       
   441 
       
   442     //-- adjust file size for very small volumes
       
   443     TUint32 fillFileSz = (maxClusters/KMaxFiles)*clustSz;
       
   444     if(fillFileSz*KMaxFiles >= 0.8*volInfo.iFree) //-- take into account the size of the directory with 1000 files.
       
   445     {
       
   446         if(fillFileSz <= clustSz)
       
   447         {
       
   448             test.Printf(_L("Can't create %d files; skipping the test!\n"), KMaxFiles);
       
   449             return EFalse;
       
   450         }
       
   451 
       
   452         fillFileSz -= clustSz;
       
   453     }
       
   454 
       
   455     //-- create the first file on the volume. It will be deleted then in order to create 1 free FAT entry
       
   456     //-- in the very beginnng of the FAT. So, the size of this file shan't be more that 1 sector/cluster.
       
   457     nRes = CreateEmptyFile(TheFs, KFirstFileName, 100);
       
   458     test_KErrNone(nRes);
       
   459 
       
   460 
       
   461     //-- to avoid affected timings in UREL mode.
       
   462     WaitForFatBkGndActivityEnd();
       
   463 
       
   464     //-- disable FAT test utils print out, it affects measured time when we create empty files
       
   465     EnablePrintOutput(EFalse);
       
   466 
       
   467     //-- create KMaxFiles files on the volume
       
   468     for(TInt i=0; i<KMaxFiles; ++i)
       
   469     {
       
   470         //-- create empty file
       
   471         MakeFileName(buf, i);
       
   472 
       
   473         timeStart.UniversalTime(); //-- take start time
       
   474 
       
   475         nRes = CreateEmptyFile(TheFs, buf, fillFileSz);
       
   476 
       
   477         timeEnd.UniversalTime(); //-- take end time
       
   478         usTotalTime += (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   479 
       
   480         test_KErrNone(nRes);
       
   481         //-- put its id number to the array.
       
   482         aFTagArray.AppendL(i);
       
   483 
       
   484         if((i % 100) == 0)
       
   485             test.Printf(_L("*"));
       
   486 
       
   487     }
       
   488 
       
   489     EnablePrintOutput(ETrue); //-- Enable FAT test utils print out
       
   490 
       
   491     test.Printf(_L("\n#--> Created %d files in %d ms\n"), KMaxFiles, (TUint32)usTotalTime/K1mSec);
       
   492 
       
   493     return ETrue;
       
   494 }
       
   495 
       
   496 //----------------------------------------------------------------------------------------------
       
   497 //! @SYMTestCaseID      PBASE-T_FATCACHE_BM-0691
       
   498 //! @SYMTestType        PT
       
   499 //! @SYMPREQ            PREQ1721
       
   500 //! @SYMTestCaseDesc    Check that all FAT copies are the same.
       
   501 //!
       
   502 //! @SYMTestActions
       
   503 //!                     0   read all available FAT copies and compare them
       
   504 //!
       
   505 //! @SYMTestExpectedResults all FAT copies on the vollume must be the same.
       
   506 //! @SYMTestPriority        High
       
   507 //! @SYMTestStatus          Implemented
       
   508 //----------------------------------------------------------------------------------------------
       
   509 void CheckFatCopies()
       
   510 {
       
   511     test.Next(_L("Comparing FATs...\n"));
       
   512 
       
   513     TFatBootSector bootSec;
       
   514 
       
   515     TInt nRes = ReadBootSector(TheFs, gDriveNum, 0x00, bootSec);
       
   516     test_KErrNone(nRes);
       
   517 
       
   518     const TInt numFATs = bootSec.NumberOfFats();
       
   519     if(numFATs < 2)
       
   520     {//-- only one FAT, nothing to compare with.
       
   521         test.Printf(_L("The volume has only 1 FAT. Nothing to do.\n"));
       
   522         return;
       
   523     }
       
   524 
       
   525     const TUint32 bytesPerSec = bootSec.BytesPerSector();
       
   526     const TUint32 posFat1Start =  bootSec.FirstFatSector() * bytesPerSec;
       
   527     const TUint32 fatSize = bootSec.TotalFatSectors() * bytesPerSec;
       
   528 
       
   529     RBuf8 fatBuf1;
       
   530     RBuf8 fatBuf2;
       
   531 
       
   532     nRes = fatBuf1.CreateMax(bytesPerSec);
       
   533     test_KErrNone(nRes);
       
   534 
       
   535     nRes = fatBuf2.CreateMax(bytesPerSec);
       
   536     test_KErrNone(nRes);
       
   537 
       
   538     //-- read FAT sector by sector comparing all copies
       
   539     TUint32 currPos = posFat1Start;
       
   540     for(TUint cntSectors=0; cntSectors<bootSec.TotalFatSectors(); ++cntSectors)
       
   541     {
       
   542         //-- read a sector of FAT#0
       
   543         nRes = MediaRawRead(TheFs, gDriveNum, currPos, bytesPerSec, fatBuf1);
       
   544         test_KErrNone(nRes);
       
   545 
       
   546         //-- read the same sector from other copies of FAT and compare with FAT#0
       
   547         for(TInt currFat=1; currFat<numFATs; ++currFat)
       
   548         {
       
   549             nRes = MediaRawRead(TheFs, gDriveNum, (currFat*fatSize + currPos), bytesPerSec, fatBuf2);
       
   550             test_KErrNone(nRes);
       
   551 
       
   552             //-- compare the buffer to FAT#0
       
   553             if(fatBuf1.CompareF(fatBuf2) !=0)
       
   554             {//-- current FAT is different from FAT0
       
   555              test.Printf(_L("FAT#%d differs from FAT#0! FAT sector:%d, media Sector:%d\n"), currFat, cntSectors, cntSectors+bootSec.FirstFatSector());
       
   556              test(0);
       
   557             }
       
   558 
       
   559         }
       
   560 
       
   561 
       
   562         currPos+=bytesPerSec;
       
   563     }
       
   564 
       
   565 
       
   566     fatBuf1.Close();
       
   567     fatBuf2.Close();
       
   568 
       
   569 }
       
   570 
       
   571 //----------------------------------------------------------------------------------------------
       
   572 //! @SYMTestCaseID      PBASE-T_FATCACHE_BM-0688
       
   573 //! @SYMTestType        PT
       
   574 //! @SYMPREQ            PREQ1721
       
   575 //! @SYMTestCaseDesc    Create the file whose FAT entries will go to the end of the FAT table and measure the time taken.
       
   576 //!
       
   577 //! @SYMTestActions
       
   578 //!                     0   delete a file in the very beginning of the FAT
       
   579 //!                     1   remount file system
       
   580 //!                     2   create a larger file finishing at the end of FAT, measure time taken
       
   581 //!
       
   582 //! @SYMTestExpectedResults successful files creation
       
   583 //! @SYMTestPriority        High
       
   584 //! @SYMTestStatus          Implemented
       
   585 //----------------------------------------------------------------------------------------------
       
   586 
       
   587 /**
       
   588     Create the file whose FAT entries will go to the end of the FAT table and measure the time taken.
       
   589     preconditions:
       
   590     1. The FAT table must be almost full already. This is done previously in DoCreateFiles().
       
   591     2. There shall be a small file in the very beginning of the FAT which this test deletes and remounts the FS.
       
   592        this will cause "the last known free cluster"  in the FAT to be set to the beginning of the FAT.
       
   593 
       
   594     Then when we create a larger file, whole occupied FAT region will be scanned for the free cluster.
       
   595 */
       
   596 void CreateLastFile()
       
   597 {
       
   598     test.Next(_L("Create a file in the end of FAT\n"));
       
   599 
       
   600     TTime   timeStart;
       
   601     TTime   timeEnd;
       
   602     TInt64  usTotalTime=0;
       
   603 
       
   604     TInt nRes;
       
   605 
       
   606 
       
   607     //-- 1. delete the first file on the volume (see KFirstFileName & DoCreateFiles()
       
   608     //-- it will create free FAT entry in the very beginning.
       
   609     nRes = TheFs.Delete(KFirstFileName);
       
   610     test_KErrNone(nRes);
       
   611 
       
   612 
       
   613     //-- 2. remount file system, reset caches etc. The first known free cluster will be number 2 or 3, because of the point 1.
       
   614     //-- the rest of the FAT is filled, because we've created plenty of files in the DoCreateFiles()
       
   615     DoRemountFS(gDriveNum);
       
   616 
       
   617     //-- 3. create a file that will occupy more that 2 clusters; the 1st cluster of it will be in the very beginning of the FAT,
       
   618     //-- and the rest will be in the very end of the FAT. Measure the time taken to walk all FAT when searching free entry.
       
   619     _LIT(KLastFn, "\\last-last.file");
       
   620 
       
   621     test(gBootSector.IsValid());
       
   622 
       
   623     const TUint32 clustSz = gBootSector.SectorsPerCluster() * gBootSector.BytesPerSector();
       
   624 
       
   625 
       
   626     //-- disable FAT test utils print out, it affects measured time
       
   627     EnablePrintOutput(EFalse);
       
   628 
       
   629     timeStart.UniversalTime(); //-- take start time
       
   630 
       
   631     //-- create an empty file, it is supposed to be placed in the very end of FAT (FAT table is almost full because of the
       
   632     //-- previous test)
       
   633     nRes = CreateEmptyFile(TheFs, KLastFn, 7*clustSz);
       
   634 
       
   635     timeEnd.UniversalTime(); //-- take end time
       
   636     usTotalTime = (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   637 
       
   638     test_KErrNone(nRes);
       
   639 
       
   640     test.Printf(_L("#--> file at the end of FAT created in %d ms\n"), (TUint32)usTotalTime/K1mSec);
       
   641 
       
   642     //-- delete the file
       
   643     nRes = TheFs.Delete(KLastFn);
       
   644     test_KErrNone(nRes);
       
   645 
       
   646     EnablePrintOutput(ETrue); //-- Enable FAT test utils print out
       
   647 }
       
   648 
       
   649 //-------------------------------------------------------------------
       
   650 /**
       
   651     Create 100 directories in the root and measure time
       
   652 */
       
   653 void DoCreateDirsInRoot()
       
   654 {
       
   655     test.Next(_L("Measure time to create many directories in the Root.\n"));
       
   656 
       
   657     if(!Is_Fat32(TheFs, gDriveNum))
       
   658     {
       
   659         test.Printf(_L("This test requires FAT32, skipping\n"));
       
   660         return;
       
   661     }
       
   662 
       
   663     TTime   timeStart;
       
   664     TTime   timeEnd;
       
   665     TInt64  usTotalTime=0;
       
   666     TFileName dirName;
       
   667 
       
   668     //-- remount file system, reset caches etc. The first known free cluster will be number 2 or 3
       
   669     DoRemountFS(gDriveNum);
       
   670 
       
   671     //-- disable FAT test utils print out, it affects measured time
       
   672     EnablePrintOutput(EFalse);
       
   673 
       
   674     timeStart.UniversalTime(); //-- take start time
       
   675 
       
   676     //-- create some subdirectories in the root dir and measure time
       
   677     const TInt KMaxDirs = 100;
       
   678     for(TInt i=0; i<KMaxDirs; ++i)
       
   679     {
       
   680         dirName.Format(_L("\\directory%04d\\"), i);
       
   681         TInt nRes = TheFs.MkDir(dirName);
       
   682         test_KErrNone(nRes);
       
   683     }
       
   684 
       
   685     timeEnd.UniversalTime(); //-- take end time
       
   686     usTotalTime = (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   687 
       
   688     test.Printf(_L("#--> %d Dirs. created in %d ms\n"), KMaxDirs, (TUint32)usTotalTime/K1mSec);
       
   689 
       
   690     EnablePrintOutput(ETrue); //-- Enable FAT test utils print out
       
   691 }
       
   692 
       
   693 //----------------------------------------------------------------------------------------------
       
   694 //! @SYMTestCaseID      PBASE-T_FATCACHE_BM-0693
       
   695 //! @SYMTestType        PT
       
   696 //! @SYMPREQ            PREQ1721
       
   697 //! @SYMTestCaseDesc    Create a large file (2G max) and measure the time. Then delete this file and measure time taken
       
   698 //!
       
   699 //! @SYMTestActions
       
   700 //!                     0   quick format the volume
       
   701 //!                     1   create emply file that takes either 80% of the volume of 2G max, masure time taken
       
   702 //!                     2   remount FS
       
   703 //!                     3   delete this file and measure time taken
       
   704 //!
       
   705 //! @SYMTestExpectedResults successful files creation/deletion
       
   706 //! @SYMTestPriority        High
       
   707 //! @SYMTestStatus          Implemented
       
   708 //----------------------------------------------------------------------------------------------
       
   709 static void CreateLargeFile()
       
   710 {
       
   711     test.Next(_L("Create a large file and measure time\n"));
       
   712 
       
   713     FormatVolume(ETrue); //-- quick format the volume.
       
   714 
       
   715     _LIT(KBigFileName, "\\BigFile.big");
       
   716 
       
   717     test(gBootSector.IsValid());
       
   718 
       
   719     //-- calculate the size of the file, it shall be max 2G or take almost all volume
       
   720     TVolumeInfo volInfo;
       
   721     TInt nRes;
       
   722 
       
   723     nRes = TheFs.Volume(volInfo, gDriveNum);
       
   724     test_KErrNone(nRes);
       
   725 
       
   726     const TUint32 clustSz = gBootSector.SectorsPerCluster() * gBootSector.BytesPerSector();
       
   727     const TUint32 maxClusters = (TUint32)(volInfo.iFree / clustSz);
       
   728 
       
   729     const TUint32 clustersPer1G = K1GigaByte / clustSz;
       
   730     const TUint32 clustersPer2G = 2*clustersPer1G;
       
   731 
       
   732     TUint32 fileClusters=0;
       
   733     if(maxClusters*0.8 < clustersPer2G)
       
   734         fileClusters = (TUint32)(maxClusters*0.8);
       
   735     else
       
   736         fileClusters = (TUint32)(clustersPer2G*0.8);
       
   737 
       
   738     const TUint32 fileSize = fileClusters*clustSz;
       
   739 
       
   740     //-- create empty file and measure time
       
   741     TTime   timeStart;
       
   742     TTime   timeEnd;
       
   743     TInt64  usTimeCreate=0;
       
   744     TInt64  usTimeDelete=0;
       
   745 
       
   746     timeStart.UniversalTime(); //-- take start time
       
   747     nRes = CreateEmptyFile(TheFs, KBigFileName, fileSize);
       
   748     timeEnd.UniversalTime(); //-- take end time
       
   749     test_KErrNone(nRes);
       
   750 
       
   751     usTimeCreate = (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   752 
       
   753     //-- remount file system, reset caches etc.
       
   754     DoRemountFS(gDriveNum);
       
   755 
       
   756     //-- delete the file
       
   757     timeStart.UniversalTime(); //-- take start time
       
   758     nRes = TheFs.Delete(KBigFileName);
       
   759     timeEnd.UniversalTime(); //-- take end time
       
   760 
       
   761     test_KErrNone(nRes);
       
   762     usTimeDelete = (timeEnd.MicroSecondsFrom(timeStart)).Int64();
       
   763 
       
   764     test.Printf(_L("#--> Big file sz:%u created:%d ms, deleted:%d ms\n"), fileSize, (TUint32)(usTimeCreate/K1mSec) , (TUint32)(usTimeDelete/K1mSec));
       
   765 
       
   766 }
       
   767 
       
   768 
       
   769 //-------------------------------------------------------------------
       
   770 /**
       
   771     Start tests.
       
   772 */
       
   773 void RunTest()
       
   774 {
       
   775     test.Printf(_L("Prepare the volume for BM testing...\n"));
       
   776 
       
   777     test(pFTagArray != NULL);
       
   778     CFileTagsArray &fTagArray = *pFTagArray;
       
   779     fTagArray.Reset();
       
   780 
       
   781     //-- full format the drive
       
   782     FormatVolume(EFalse);
       
   783 
       
   784     test.Printf(_L("\n#--> t_fatcache_bm\n"));
       
   785 
       
   786     //-- create test directory.
       
   787     MakeDir(KDirName);
       
   788 
       
   789     //-- 1. create KMaxFiles files to fill in space in FAT table.
       
   790     if(!DoCreateFiles(fTagArray))
       
   791         return; //-- test is inconsistent
       
   792 
       
   793 
       
   794     //-- 1.1 create a file in the very end of the full volume (FAT table is almost full). Measure time taken
       
   795     CreateLastFile();
       
   796 
       
   797     //-- 1.2 create multiple directories in the root and measure time
       
   798 //    DoCreateDirsInRoot();
       
   799 
       
   800     //-- 2. randomly merge some small files to bigger ones that will be fragmented
       
   801     DoMergeFiles(fTagArray);
       
   802 
       
   803     //-- 3. randomly shuffle file tags in the array
       
   804     ShuffleArray(fTagArray);
       
   805 
       
   806     //-- 4. measure file open and seek time
       
   807     MeasureSeekTime(fTagArray);
       
   808 
       
   809     //-- 4.5 Check that all copies of FAT are the same.
       
   810     CheckFatCopies();
       
   811 
       
   812     //-- 5. delete all files and print out time taken
       
   813     DeleteAllFiles(fTagArray);
       
   814 
       
   815     //-- 6. Create a large file (2G max) and measure the time
       
   816     //!!!!
       
   817     CreateLargeFile();
       
   818 
       
   819 }
       
   820 
       
   821 
       
   822 
       
   823 //-------------------------------------------------------------------
       
   824 static void WaitForFatBkGndActivityEnd()
       
   825 {
       
   826     //-- if we work in release mode, we need to use a hardcore solution to wait until possible FAT background activity finishes
       
   827     //-- because transient FAT threads can affect timings (e.g. creating a file may need waiting to FAT background thread to
       
   828     //-- parse some portion of FAT) etc.
       
   829     //-- for debug mode background FAT activity is disabled in InitGlobals() and timings are not precise anyway
       
   830     //-- for release mode we just need to wait some time
       
   831     #ifndef _DEBUG
       
   832     const TInt KWaitTimeSec = 10;
       
   833     test.Printf(_L("waiting %d sec...\n"), KWaitTimeSec);
       
   834     User::After(KWaitTimeSec*K1Sec);
       
   835     #endif
       
   836 
       
   837 }
       
   838 
       
   839 
       
   840 
       
   841 //-------------------------------------------------------------------
       
   842 
       
   843 /**
       
   844     Dismounts and mounts the FS on a drive aDrive
       
   845     This will cause resetting "last known free cluster number" value in the FAT table implementation in FSY.
       
   846     (Mounting enhancements are disabled.) Empty the caches etc.
       
   847 */
       
   848 static void DoRemountFS(TInt aDrive)
       
   849 {
       
   850     TInt nRes = RemountFS(TheFs, aDrive);
       
   851     test_KErrNone(nRes);
       
   852 
       
   853     //-- get volume info, this is a trick that can help avoiding asynchronous FAT mount in UREL mode
       
   854     //TVolumeInfo v;
       
   855     //nRes = TheFs.Volume(v);
       
   856 
       
   857     //-- to avoid affected timings in UREL mode.
       
   858     WaitForFatBkGndActivityEnd();
       
   859 }
       
   860 
       
   861 
       
   862 //-------------------------------------------------------------------
       
   863 
       
   864 /** initialise test global objects */
       
   865 static void InitGlobals()
       
   866 {
       
   867     //-- initialise random generator
       
   868     gRndSeed = 0x67fc1a9;
       
   869 
       
   870     //-- construct file numbers array
       
   871     pFTagArray = new CFileTagsArray(KMaxFiles);
       
   872     test(pFTagArray != NULL);
       
   873     pFTagArray->SetReserveL(KMaxFiles);
       
   874 
       
   875     //-- define a propery which will control mount process in the fsy.
       
   876     //-- The property key is a drive number being tested
       
   877     _LIT_SECURITY_POLICY_PASS(KTestPropPolicy);
       
   878     TInt nRes = RProperty::Define(KThisTestSID, gDriveNum, RProperty::EInt, KTestPropPolicy, KTestPropPolicy);
       
   879     test(nRes == KErrNone || nRes == KErrAlreadyExists);
       
   880 
       
   881     //-- disable all volume mount enhancements, like asynch mount and FSInfo.
       
   882     //-- this works only in debug mode.
       
   883     nRes = RProperty::Set(KThisTestSID, gDriveNum, (TInt)KMntProp_DisableALL);
       
   884     test_KErrNone(nRes);
       
   885 
       
   886 }
       
   887 
       
   888 /** destroy test global objects */
       
   889 static void DestroyGlobals()
       
   890 {
       
   891     delete pFTagArray;
       
   892 
       
   893     //-- delete test property
       
   894     RProperty::Delete(KThisTestSID, gDriveNum);
       
   895 
       
   896 }
       
   897 
       
   898 
       
   899 //-------------------------------------------------------------------
       
   900 void CallTestsL()
       
   901     {
       
   902 
       
   903     //-- set up console output
       
   904     Fat_Test_Utils::SetConsole(test.Console());
       
   905 
       
   906     TInt nRes=TheFs.CharToDrive(gDriveToTest, gDriveNum);
       
   907     test(nRes==KErrNone);
       
   908 
       
   909     //-- check if this is FAT
       
   910     if(!Is_Fat(TheFs, gDriveNum))
       
   911     {
       
   912         test.Printf(_L("Skipping. This test requires FAT drive.\n"));
       
   913         return;
       
   914     }
       
   915 
       
   916     //-- check this is not the internal ram drive
       
   917     TVolumeInfo v;
       
   918     nRes = TheFs.Volume(v);
       
   919     test(nRes==KErrNone);
       
   920     if(v.iDrive.iMediaAtt & KMediaAttVariableSize)
       
   921         {
       
   922         test.Printf(_L("Skipping. Internal ram drive not tested.\n"));
       
   923         return;
       
   924         }
       
   925 
       
   926 
       
   927     //-------------------------------------
       
   928     PrintDrvInfo(TheFs, gDriveNum);
       
   929 
       
   930     InitGlobals();
       
   931 
       
   932     RunTest();
       
   933 
       
   934     //-------------------------------------
       
   935     DestroyGlobals();
       
   936 
       
   937     }
       
   938 
       
   939 
       
   940 
       
   941 
       
   942 
       
   943 
       
   944 
       
   945 
       
   946 
       
   947 
       
   948 
       
   949 
       
   950 
       
   951 
       
   952 
       
   953 
       
   954