kerneltest/e32test/pccd/t_med_writebm.cpp
changeset 43 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 43:96e5fb8b040d
       
     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 // e32test\pccd\t_med_writebm.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20 */
       
    21 
       
    22 #define __E32TEST_EXTENSION__
       
    23 
       
    24 #include <e32test.h>
       
    25 #include <f32fsys.h>
       
    26 #include <e32math.h>
       
    27 
       
    28 /*
       
    29     SD/MMC/other media benchmark test
       
    30     Writes data to the media and prints out time taken (microseconds).
       
    31     Works on TBusLocalDrive level. May require a script to filter the results.
       
    32 
       
    33     Principle of operation:
       
    34     In the simple case scenario the user specifies media start and end position in bytes,
       
    35     write buffer size (window size), the number of write repetitions (optional) and write position increment.
       
    36     
       
    37     The test fills buffer with random data, writes it to the media (probably several times); prints out the time taken;
       
    38     increments or decrements window position; goto begin.  Test finishes when the window slides outside specified beginning or end media position.
       
    39 
       
    40     It more complex case we have 2 windows. It is useful for FAT emulation.
       
    41     
       
    42     -------------------------------------------
       
    43     Command line shall look like this:
       
    44     drv=[0..25] pos=xxx:yyy [wrep=<number>] wn=[1,2] w1sz=<number> w1pi=<number> [w2sz=<number> w2pi=<number>]
       
    45 
       
    46     where:
       
    47     drv=N           local drive physical number for 1st MMC slot on H2 & H4 it will be 1, see variantmediadef.h
       
    48     pos=xxx:yyy     xxx start media position, yyy end media position in bytes. The test will be writing data in the range xxx-yyy
       
    49     wrep=N          optional. Specifies how many times the window will be written to the media, just for more precise time calculation. Default is 1.
       
    50     wn=N            Number of data windows being written on the media. can be 1 or 2
       
    51     
       
    52     w1sz=N          Size of the data window #1 in bytes. Must be > 0
       
    53     w1pi=N          Media position increment for the window #1. if positive, the window will be moving from xxx to yyy (see media pos parameter); 
       
    54                     if 0, the window won't change its position; if <0, the window will be moving from yyy to xxx
       
    55 
       
    56     w2sz            the same for the window #2 if it is specified
       
    57     w2pi            the same for the window #2 if it is specified
       
    58 
       
    59     The test will finish when one of the windows slides across the media boundaries xxx of yyy. If you specify w1pi=0 or both w1pi=0 w2pi=0
       
    60     it may run forever :)
       
    61 
       
    62     Be careful, all information on the medium will be lost !!!
       
    63 */
       
    64 
       
    65 RTest test(_L("MMC/SD write performance test"));
       
    66 
       
    67 TBusLocalDrive BusLocalDrv;
       
    68 RFs            Fs;
       
    69 
       
    70 RBuf8   gWriteBuffer1;
       
    71 RBuf8   gWriteBuffer2;
       
    72 
       
    73 TInt    gLocalDrvNum = -1;       //-- LOCAL physical drive number (see Estart.txt)
       
    74 TBool   gChangeFlag;
       
    75 
       
    76 TUint   gWindowsNum = 0;         //-- number of windows being written
       
    77 
       
    78 TUint32 gWriteBufSize1     = 0;  //-- write buffer 1 size, bytes
       
    79 TInt32  gWriteGranularity1 = 0;  //-- write granularity 1 (write buffer position increment) 
       
    80 
       
    81 TUint32 gWriteBufSize2     = 0;  //-- write buffer 2 size, bytes
       
    82 TInt32  gWriteGranularity2 = 0;  //-- write granularity 2 (write buffer position increment) 
       
    83 
       
    84 TInt64  gMediaStartPos = 0;      //-- media start position
       
    85 TInt64  gMediaEndPos = 0;        //-- media end position
       
    86 
       
    87 TUint   gNumWrites = 1;          //-- number of buffer writes to the media
       
    88 
       
    89 
       
    90 //---------------------------------------------------------------------------------
       
    91 
       
    92 void RndFillBuf(TDes8& aBuf);
       
    93 
       
    94 //---------------------------------------------------------------------------------
       
    95 
       
    96 /**
       
    97     The main part of the test, actually. Writes 1 or 2 buffers to the media (possibly several times) and 
       
    98     prints out the time taken.
       
    99 */
       
   100 void DoWriteBMTest(void)
       
   101 {
       
   102     test.Next(_L("Performing write benchmark test.\n"));
       
   103 
       
   104     TInt    nRes;
       
   105     TTime   timeStart;
       
   106     TTime   timeEnd;
       
   107     
       
   108     //-- if window pos increment is <0, it will move from end to the beginning position, backwards   
       
   109     TInt64 currMediaPos1 =  (gWriteGranularity1 >=0) ? gMediaStartPos : gMediaEndPos-gWriteBufSize1;
       
   110     TInt64 currMediaPos2 =  (gWriteGranularity2 >=0) ? gMediaStartPos : gMediaEndPos-gWriteBufSize2;
       
   111 
       
   112     if(gWindowsNum == 1) //-- we have only 1 window 
       
   113     {
       
   114         currMediaPos2 = 0;
       
   115         gWriteGranularity2 = 0;
       
   116     }
       
   117 
       
   118 	RndFillBuf(gWriteBuffer1); 
       
   119 	if(gWindowsNum == 2)
       
   120 		RndFillBuf(gWriteBuffer2); 
       
   121 
       
   122     for(;;)
       
   123     {
       
   124         if(currMediaPos1 <0 || (currMediaPos1 + gWriteBufSize1) > gMediaEndPos)
       
   125             break;
       
   126 
       
   127         if(currMediaPos2 <0 || (currMediaPos2 + gWriteBufSize2) > gMediaEndPos)
       
   128             break;
       
   129 
       
   130         timeStart.UniversalTime(); //-- take start time
       
   131 
       
   132         for(TUint i=0; i<gNumWrites; ++i)
       
   133         {
       
   134             nRes = BusLocalDrv.Write(currMediaPos1, gWriteBuffer1); //-- write window 1
       
   135             test_KErrNone(nRes);
       
   136 
       
   137             if(gWindowsNum == 2)
       
   138             {
       
   139                 nRes = BusLocalDrv.Write(currMediaPos2, gWriteBuffer2); //-- write window 2
       
   140                 test_KErrNone(nRes);
       
   141             }
       
   142         }//for(TUint i=0; i<gNumWrites; ++i)
       
   143 
       
   144         timeEnd.UniversalTime(); //-- take end time
       
   145         
       
   146         TTimeIntervalMicroSeconds  usElapsed=timeEnd.MicroSecondsFrom(timeStart);
       
   147         TInt64 usTaken = usElapsed.Int64()/gNumWrites;
       
   148 
       
   149         //-- print out the result
       
   150 
       
   151         test.Printf(_L("~#pos:%lu:%lu, time:%d us\n"), currMediaPos1, currMediaPos2, (TInt32)usTaken);
       
   152 
       
   153         //-- move windows
       
   154         currMediaPos1 += gWriteGranularity1;
       
   155         currMediaPos2 += gWriteGranularity2;
       
   156     }
       
   157 
       
   158 }
       
   159 
       
   160 
       
   161 //---------------------------------------------------------------------------------
       
   162 
       
   163 /** fill a given buffer with random bytes */
       
   164 void RndFillBuf(TDes8& aBuf)
       
   165 {
       
   166     static TInt64 rndSeed = Math::Random();
       
   167 
       
   168     //-- ?? optimise here ??
       
   169     for(TInt i=0; i<aBuf.Size(); ++i)
       
   170     {
       
   171         aBuf[i] = (TUint8)Math::Rand(rndSeed);
       
   172     }
       
   173 }
       
   174 
       
   175 
       
   176 //---------------------------------------------------------------------------------
       
   177 
       
   178 /** Initialise environment */
       
   179 TBool Initialise()
       
   180 {
       
   181     //-- print out some parameters:
       
   182     test.Printf(_L("~#Local Drive:%d\n"), gLocalDrvNum);
       
   183     test.Printf(_L("~#MediaPos:%lu:%lu\n"), gMediaStartPos, gMediaEndPos);
       
   184     test.Printf(_L("~#WinNum:%d\n"), gWindowsNum);
       
   185     test.Printf(_L("~#NumWrites:%d\n"), gNumWrites);
       
   186     test.Printf(_L("~#Window1 sz:%d, posInc:%d \n"), gWriteBufSize1, gWriteGranularity1);
       
   187 
       
   188     if(gWindowsNum == 2)
       
   189     {
       
   190         test.Printf(_L("~#Window2 sz:%d, posInc:%d \n"), gWriteBufSize2, gWriteGranularity2);
       
   191     }
       
   192 
       
   193     
       
   194     test((gLocalDrvNum >= EDriveA) && (gLocalDrvNum <= EDriveZ));
       
   195     test(gMediaStartPos >=0 && gMediaEndPos >gMediaStartPos);
       
   196     test(gWindowsNum == 1 || gWindowsNum == 2);
       
   197     test(gWriteBufSize1 > 0);
       
   198     if(gWindowsNum == 2)
       
   199     {
       
   200         test(gWriteBufSize2 > 0);
       
   201     }
       
   202     test(gNumWrites > 0);
       
   203 
       
   204     
       
   205     TInt nRes;
       
   206     nRes = Fs.Connect();
       
   207     test_KErrNone(nRes);
       
   208 
       
   209     //-- connect to the TBusLocalDrive
       
   210     test.Printf(_L("Connecting to the PHYSICAL drive #%d\n"), gLocalDrvNum);
       
   211 
       
   212     nRes = BusLocalDrv.Connect(gLocalDrvNum, gChangeFlag);
       
   213     test_KErrNone(nRes);
       
   214 
       
   215     TLocalDriveCapsV2 info;
       
   216     TPckg<TLocalDriveCapsV2> infoPckg(info);
       
   217     nRes = BusLocalDrv.Caps(infoPckg);
       
   218     test_KErrNone(nRes);
       
   219 
       
   220     //-- create write buffer 1
       
   221     nRes=gWriteBuffer1.CreateMax(gWriteBufSize1);
       
   222     test_KErrNone(nRes);
       
   223 
       
   224 
       
   225     //-- create write buffer 2
       
   226     if(gWindowsNum == 2)
       
   227     {
       
   228         nRes=gWriteBuffer2.CreateMax(gWriteBufSize2);
       
   229         test_KErrNone(nRes);
       
   230     }
       
   231 
       
   232     return ETrue;
       
   233 }
       
   234 
       
   235 //---------------------------------------------------------------------------------
       
   236 
       
   237 /** Finalise environment */
       
   238 void Finalise(void)
       
   239 {
       
   240     BusLocalDrv.Disconnect();
       
   241     BusLocalDrv.Close();
       
   242     
       
   243     gWriteBuffer1.Close();
       
   244     gWriteBuffer2.Close();
       
   245 
       
   246     Fs.Close();
       
   247 }
       
   248 
       
   249 
       
   250 /**
       
   251     Just a helper method. Looks for a given pattern in the given string and returns the rest of the found token.
       
   252     @return KErrNotFound if the aPattern wasn't found in aSrc
       
   253             KErrNone otherwise and the rest of the token in aToken
       
   254 */
       
   255 TInt DoFindToken(const TDesC& aSrc, const TDesC& aPattern,TPtrC& aToken)
       
   256 {
       
   257     TLex    lex(aSrc);
       
   258     TPtrC   token;
       
   259 
       
   260     for(;;)
       
   261     {
       
   262         lex.SkipSpace();
       
   263         token.Set(lex.NextToken());
       
   264     
       
   265         if(token.Length() == 0)
       
   266         {
       
   267             test.Printf(_L("Parameter %S not found!\n"), &aPattern);   
       
   268             return KErrNotFound;            
       
   269         }
       
   270 
       
   271         if(token.FindF(aPattern) == 0)
       
   272         {//-- found a requires patern, extract substring next to it
       
   273             aToken.Set(token.Right(token.Length() - aPattern.Length()));
       
   274             break;
       
   275         }
       
   276 
       
   277 
       
   278     }
       
   279 
       
   280     return KErrNone;
       
   281 }
       
   282 
       
   283 
       
   284 /**
       
   285     Parse the command line, which shall look like:
       
   286     drv=[0..25] pos=xxx:yyy [wrep=<number>] wn=[1,2] w1sz=<number> w1pi=<number> [w2sz=<number> w2pi=<number>]
       
   287 */
       
   288 TBool ParseCommandLine(void)
       
   289 {
       
   290     TBuf<0x100> cmdLine;
       
   291     User::CommandLine(cmdLine);
       
   292 
       
   293     cmdLine.LowerCase();
       
   294 
       
   295     test.Printf(_L("Command line:\n"));   
       
   296     test.Printf(cmdLine);   
       
   297     test.Printf(_L("\n"));   
       
   298 
       
   299     TLex lexParam;
       
   300 
       
   301     TInt    nVal;
       
   302     TUint   uVal;
       
   303     TInt    nRes;
       
   304     
       
   305     TPtrC   token;
       
   306     
       
   307     //-- process "drv" parameter. It shall look like: "drv=1"
       
   308     //-- this is a physical number of a local drive
       
   309     if(DoFindToken(cmdLine, _L("drv="), token) != KErrNone)
       
   310         return  EFalse;
       
   311 
       
   312     lexParam.Assign(token);
       
   313     lexParam.SkipSpace();
       
   314     nRes = lexParam.Val(nVal);
       
   315     if(nRes!= KErrNone || nVal < EDriveA || nVal > EDriveZ)
       
   316     {
       
   317             test.Printf(_L("Invalid 'drv' parameter value!\n"));   
       
   318             return EFalse;
       
   319     }
       
   320 
       
   321     gLocalDrvNum = nVal;
       
   322 
       
   323 
       
   324     //-- process "pos" parameter It shall look like: "pos=xxx:yyy" where "xxx" is a start media position, "yyy" end media position
       
   325     //-- It specifies start and end media position
       
   326     if(DoFindToken(cmdLine, _L("pos="), token) != KErrNone)
       
   327         return  EFalse;
       
   328 
       
   329     lexParam.Assign(token);
       
   330     lexParam.SkipSpace();
       
   331 
       
   332     TInt64 startPos;
       
   333     TInt64 endPos;
       
   334                 
       
   335     //-- start media position
       
   336     nRes = lexParam.Val(startPos);
       
   337     if(nRes!= KErrNone || startPos< 0)
       
   338     {
       
   339         test.Printf(_L("invalid start 'pos' value!\n"));   
       
   340         return EFalse;
       
   341     }
       
   342 
       
   343     //-- delimiter
       
   344     lexParam.SkipSpace();
       
   345     if(lexParam.Get() != ':')
       
   346     {
       
   347         test.Printf(_L("invalid 'pos' parameter!\n"));   
       
   348         return EFalse;
       
   349     }
       
   350 
       
   351     //-- end media position
       
   352     lexParam.SkipSpace();
       
   353     nRes = lexParam.Val(endPos);
       
   354     if(nRes!= KErrNone || endPos < 0)
       
   355     {
       
   356         test.Printf(_L("invalid end 'pos' value!\n"));   
       
   357         return EFalse;
       
   358     }
       
   359 
       
   360     gMediaStartPos = startPos;
       
   361     gMediaEndPos = endPos;
       
   362 
       
   363 
       
   364     //-- process "wn" parameter It shall look like: "wn=1" or "wn=2"
       
   365     //-- It specifies number of sliding windows.
       
   366     lexParam.SkipSpace();
       
   367     if(DoFindToken(cmdLine, _L("wn="), token) != KErrNone)
       
   368         return  EFalse;
       
   369     
       
   370     lexParam.Assign(token);
       
   371     lexParam.SkipSpace();
       
   372 
       
   373     nRes = lexParam.Val(uVal);
       
   374     if(nRes!= KErrNone || uVal > 2)
       
   375     {
       
   376         test.Printf(_L("wrong 'wn' parameter value, it must be 1 or 2 !\n"));   
       
   377         return EFalse;
       
   378     }
       
   379 
       
   380     gWindowsNum = uVal;
       
   381 
       
   382 
       
   383     //-- process "w1sz" & "w1pi" parameters. They shall look like: "w1sz=16384" & "w1pi=512"
       
   384     //-- these parameters specify size and position increment for the window 1
       
   385     //-- if w1pi <0 the window will slide from the media end position to the beginning
       
   386     lexParam.SkipSpace();
       
   387     if(DoFindToken(cmdLine, _L("w1sz="), token) != KErrNone)
       
   388         return  EFalse;
       
   389 
       
   390     lexParam.Assign(token);
       
   391     lexParam.SkipSpace();
       
   392 
       
   393     nRes = lexParam.Val(uVal);
       
   394     if(nRes!= KErrNone || uVal ==0)
       
   395     {
       
   396         test.Printf(_L("wrong 'w1sz' parameter value, it must be > 0 !\n"));   
       
   397         return EFalse;
       
   398     }
       
   399 
       
   400     gWriteBufSize1 = uVal;
       
   401     
       
   402 
       
   403     lexParam.SkipSpace();
       
   404     if(DoFindToken(cmdLine, _L("w1pi="), token) != KErrNone)
       
   405         return  EFalse;
       
   406 
       
   407     lexParam.Assign(token);
       
   408     lexParam.SkipSpace();
       
   409 
       
   410     nRes = lexParam.Val(nVal);
       
   411     if(nRes!= KErrNone)
       
   412     {
       
   413         return EFalse;
       
   414     }
       
   415 
       
   416     gWriteGranularity1 = nVal;
       
   417 
       
   418     //-- process "w2sz" & "w2pi" parameters. They shall look like: "w2sz=16384" & "w2pi=512"
       
   419     //-- these parameters specify size and position increment for the window 1
       
   420     //-- if w1pi <0 the window will slide from the media end position to the beginning
       
   421     if(gWindowsNum == 2)
       
   422     {
       
   423         lexParam.SkipSpace();
       
   424         if(DoFindToken(cmdLine, _L("w2sz="), token) != KErrNone)
       
   425             return  EFalse;
       
   426 
       
   427         lexParam.Assign(token);
       
   428         lexParam.SkipSpace();
       
   429 
       
   430         nRes = lexParam.Val(uVal);
       
   431         if(nRes!= KErrNone || uVal ==0)
       
   432         {
       
   433             test.Printf(_L("wrong 'w2sz' parameter value, it must be > 0 !\n"));   
       
   434             return EFalse;
       
   435         }
       
   436 
       
   437         gWriteBufSize2 = uVal;
       
   438     
       
   439 
       
   440         lexParam.SkipSpace();
       
   441         if(DoFindToken(cmdLine, _L("w2pi="), token) != KErrNone)
       
   442             return  EFalse;
       
   443 
       
   444         lexParam.Assign(token);
       
   445         lexParam.SkipSpace();
       
   446 
       
   447         nRes = lexParam.Val(nVal);
       
   448         if(nRes!= KErrNone)
       
   449         {
       
   450             return EFalse;
       
   451         }
       
   452 
       
   453         gWriteGranularity2 = nVal;
       
   454      }
       
   455     
       
   456     //-- extract wrep=<number> parameter.
       
   457     //-- it specifies how many times buffers will be written to the media
       
   458     lexParam.SkipSpace();
       
   459     if(DoFindToken(cmdLine, _L("wrep="), token) == KErrNone)
       
   460     {
       
   461     
       
   462     
       
   463     lexParam.Assign(token);
       
   464     lexParam.SkipSpace();
       
   465 
       
   466     nRes = lexParam.Val(uVal);
       
   467     if(nRes!= KErrNone || uVal ==0 )
       
   468     {
       
   469         test.Printf(_L("wrong 'wrep' parameter value, it must be >0 !\n"));   
       
   470         return EFalse;
       
   471     }
       
   472      
       
   473         gNumWrites = uVal;
       
   474     }
       
   475     else
       
   476     {
       
   477         gNumWrites = 1;
       
   478     }
       
   479 
       
   480 
       
   481     return ETrue;
       
   482 }
       
   483 
       
   484 void PrintInfo()
       
   485 {
       
   486     test.Printf(_L("Media write benchmark test. For use mostly with mmc/sd cards.\n"));
       
   487     test.Printf(_L("Usage: See source code for command line parameters.\n"));
       
   488 }
       
   489 
       
   490 
       
   491 //---------------------------------------------------------------------------------
       
   492 
       
   493 void MainL(void)
       
   494 {
       
   495     test.Title();
       
   496     test.Start(_L("Start testing...\n"));
       
   497 
       
   498     
       
   499     //-- it will initialise global test parameters
       
   500     if(!ParseCommandLine())
       
   501     {
       
   502         PrintInfo();
       
   503         return;
       
   504     }
       
   505 
       
   506     if(!Initialise())
       
   507     {
       
   508         return; //-- something went wrong
       
   509     }
       
   510 
       
   511 
       
   512     DoWriteBMTest();
       
   513     
       
   514     Finalise();
       
   515     
       
   516     test.End();
       
   517 }
       
   518 
       
   519 
       
   520 TInt E32Main()
       
   521 {
       
   522 
       
   523     CTrapCleanup* cleanup=CTrapCleanup::New() ; // get clean-up stack
       
   524     
       
   525     TRAPD(r,MainL());
       
   526     
       
   527     delete cleanup ; // destroy clean-up stack
       
   528     
       
   529     return r;
       
   530 }
       
   531 
       
   532 
       
   533