os/kernelhwsrv/kerneltest/f32test/filesystem/fat/t_fatcache_bm.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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