os/kernelhwsrv/kerneltest/e32test/pccd/t_med_writebm.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 // 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