1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/pccd/t_med_writebm.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,533 @@
1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\pccd\t_med_writebm.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +/**
1.22 + @file
1.23 +*/
1.24 +
1.25 +#define __E32TEST_EXTENSION__
1.26 +
1.27 +#include <e32test.h>
1.28 +#include <f32fsys.h>
1.29 +#include <e32math.h>
1.30 +
1.31 +/*
1.32 + SD/MMC/other media benchmark test
1.33 + Writes data to the media and prints out time taken (microseconds).
1.34 + Works on TBusLocalDrive level. May require a script to filter the results.
1.35 +
1.36 + Principle of operation:
1.37 + In the simple case scenario the user specifies media start and end position in bytes,
1.38 + write buffer size (window size), the number of write repetitions (optional) and write position increment.
1.39 +
1.40 + The test fills buffer with random data, writes it to the media (probably several times); prints out the time taken;
1.41 + increments or decrements window position; goto begin. Test finishes when the window slides outside specified beginning or end media position.
1.42 +
1.43 + It more complex case we have 2 windows. It is useful for FAT emulation.
1.44 +
1.45 + -------------------------------------------
1.46 + Command line shall look like this:
1.47 + drv=[0..25] pos=xxx:yyy [wrep=<number>] wn=[1,2] w1sz=<number> w1pi=<number> [w2sz=<number> w2pi=<number>]
1.48 +
1.49 + where:
1.50 + drv=N local drive physical number for 1st MMC slot on H2 & H4 it will be 1, see variantmediadef.h
1.51 + pos=xxx:yyy xxx start media position, yyy end media position in bytes. The test will be writing data in the range xxx-yyy
1.52 + wrep=N optional. Specifies how many times the window will be written to the media, just for more precise time calculation. Default is 1.
1.53 + wn=N Number of data windows being written on the media. can be 1 or 2
1.54 +
1.55 + w1sz=N Size of the data window #1 in bytes. Must be > 0
1.56 + w1pi=N Media position increment for the window #1. if positive, the window will be moving from xxx to yyy (see media pos parameter);
1.57 + if 0, the window won't change its position; if <0, the window will be moving from yyy to xxx
1.58 +
1.59 + w2sz the same for the window #2 if it is specified
1.60 + w2pi the same for the window #2 if it is specified
1.61 +
1.62 + 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
1.63 + it may run forever :)
1.64 +
1.65 + Be careful, all information on the medium will be lost !!!
1.66 +*/
1.67 +
1.68 +RTest test(_L("MMC/SD write performance test"));
1.69 +
1.70 +TBusLocalDrive BusLocalDrv;
1.71 +RFs Fs;
1.72 +
1.73 +RBuf8 gWriteBuffer1;
1.74 +RBuf8 gWriteBuffer2;
1.75 +
1.76 +TInt gLocalDrvNum = -1; //-- LOCAL physical drive number (see Estart.txt)
1.77 +TBool gChangeFlag;
1.78 +
1.79 +TUint gWindowsNum = 0; //-- number of windows being written
1.80 +
1.81 +TUint32 gWriteBufSize1 = 0; //-- write buffer 1 size, bytes
1.82 +TInt32 gWriteGranularity1 = 0; //-- write granularity 1 (write buffer position increment)
1.83 +
1.84 +TUint32 gWriteBufSize2 = 0; //-- write buffer 2 size, bytes
1.85 +TInt32 gWriteGranularity2 = 0; //-- write granularity 2 (write buffer position increment)
1.86 +
1.87 +TInt64 gMediaStartPos = 0; //-- media start position
1.88 +TInt64 gMediaEndPos = 0; //-- media end position
1.89 +
1.90 +TUint gNumWrites = 1; //-- number of buffer writes to the media
1.91 +
1.92 +
1.93 +//---------------------------------------------------------------------------------
1.94 +
1.95 +void RndFillBuf(TDes8& aBuf);
1.96 +
1.97 +//---------------------------------------------------------------------------------
1.98 +
1.99 +/**
1.100 + The main part of the test, actually. Writes 1 or 2 buffers to the media (possibly several times) and
1.101 + prints out the time taken.
1.102 +*/
1.103 +void DoWriteBMTest(void)
1.104 +{
1.105 + test.Next(_L("Performing write benchmark test.\n"));
1.106 +
1.107 + TInt nRes;
1.108 + TTime timeStart;
1.109 + TTime timeEnd;
1.110 +
1.111 + //-- if window pos increment is <0, it will move from end to the beginning position, backwards
1.112 + TInt64 currMediaPos1 = (gWriteGranularity1 >=0) ? gMediaStartPos : gMediaEndPos-gWriteBufSize1;
1.113 + TInt64 currMediaPos2 = (gWriteGranularity2 >=0) ? gMediaStartPos : gMediaEndPos-gWriteBufSize2;
1.114 +
1.115 + if(gWindowsNum == 1) //-- we have only 1 window
1.116 + {
1.117 + currMediaPos2 = 0;
1.118 + gWriteGranularity2 = 0;
1.119 + }
1.120 +
1.121 + RndFillBuf(gWriteBuffer1);
1.122 + if(gWindowsNum == 2)
1.123 + RndFillBuf(gWriteBuffer2);
1.124 +
1.125 + for(;;)
1.126 + {
1.127 + if(currMediaPos1 <0 || (currMediaPos1 + gWriteBufSize1) > gMediaEndPos)
1.128 + break;
1.129 +
1.130 + if(currMediaPos2 <0 || (currMediaPos2 + gWriteBufSize2) > gMediaEndPos)
1.131 + break;
1.132 +
1.133 + timeStart.UniversalTime(); //-- take start time
1.134 +
1.135 + for(TUint i=0; i<gNumWrites; ++i)
1.136 + {
1.137 + nRes = BusLocalDrv.Write(currMediaPos1, gWriteBuffer1); //-- write window 1
1.138 + test_KErrNone(nRes);
1.139 +
1.140 + if(gWindowsNum == 2)
1.141 + {
1.142 + nRes = BusLocalDrv.Write(currMediaPos2, gWriteBuffer2); //-- write window 2
1.143 + test_KErrNone(nRes);
1.144 + }
1.145 + }//for(TUint i=0; i<gNumWrites; ++i)
1.146 +
1.147 + timeEnd.UniversalTime(); //-- take end time
1.148 +
1.149 + TTimeIntervalMicroSeconds usElapsed=timeEnd.MicroSecondsFrom(timeStart);
1.150 + TInt64 usTaken = usElapsed.Int64()/gNumWrites;
1.151 +
1.152 + //-- print out the result
1.153 +
1.154 + test.Printf(_L("~#pos:%lu:%lu, time:%d us\n"), currMediaPos1, currMediaPos2, (TInt32)usTaken);
1.155 +
1.156 + //-- move windows
1.157 + currMediaPos1 += gWriteGranularity1;
1.158 + currMediaPos2 += gWriteGranularity2;
1.159 + }
1.160 +
1.161 +}
1.162 +
1.163 +
1.164 +//---------------------------------------------------------------------------------
1.165 +
1.166 +/** fill a given buffer with random bytes */
1.167 +void RndFillBuf(TDes8& aBuf)
1.168 +{
1.169 + static TInt64 rndSeed = Math::Random();
1.170 +
1.171 + //-- ?? optimise here ??
1.172 + for(TInt i=0; i<aBuf.Size(); ++i)
1.173 + {
1.174 + aBuf[i] = (TUint8)Math::Rand(rndSeed);
1.175 + }
1.176 +}
1.177 +
1.178 +
1.179 +//---------------------------------------------------------------------------------
1.180 +
1.181 +/** Initialise environment */
1.182 +TBool Initialise()
1.183 +{
1.184 + //-- print out some parameters:
1.185 + test.Printf(_L("~#Local Drive:%d\n"), gLocalDrvNum);
1.186 + test.Printf(_L("~#MediaPos:%lu:%lu\n"), gMediaStartPos, gMediaEndPos);
1.187 + test.Printf(_L("~#WinNum:%d\n"), gWindowsNum);
1.188 + test.Printf(_L("~#NumWrites:%d\n"), gNumWrites);
1.189 + test.Printf(_L("~#Window1 sz:%d, posInc:%d \n"), gWriteBufSize1, gWriteGranularity1);
1.190 +
1.191 + if(gWindowsNum == 2)
1.192 + {
1.193 + test.Printf(_L("~#Window2 sz:%d, posInc:%d \n"), gWriteBufSize2, gWriteGranularity2);
1.194 + }
1.195 +
1.196 +
1.197 + test((gLocalDrvNum >= EDriveA) && (gLocalDrvNum <= EDriveZ));
1.198 + test(gMediaStartPos >=0 && gMediaEndPos >gMediaStartPos);
1.199 + test(gWindowsNum == 1 || gWindowsNum == 2);
1.200 + test(gWriteBufSize1 > 0);
1.201 + if(gWindowsNum == 2)
1.202 + {
1.203 + test(gWriteBufSize2 > 0);
1.204 + }
1.205 + test(gNumWrites > 0);
1.206 +
1.207 +
1.208 + TInt nRes;
1.209 + nRes = Fs.Connect();
1.210 + test_KErrNone(nRes);
1.211 +
1.212 + //-- connect to the TBusLocalDrive
1.213 + test.Printf(_L("Connecting to the PHYSICAL drive #%d\n"), gLocalDrvNum);
1.214 +
1.215 + nRes = BusLocalDrv.Connect(gLocalDrvNum, gChangeFlag);
1.216 + test_KErrNone(nRes);
1.217 +
1.218 + TLocalDriveCapsV2 info;
1.219 + TPckg<TLocalDriveCapsV2> infoPckg(info);
1.220 + nRes = BusLocalDrv.Caps(infoPckg);
1.221 + test_KErrNone(nRes);
1.222 +
1.223 + //-- create write buffer 1
1.224 + nRes=gWriteBuffer1.CreateMax(gWriteBufSize1);
1.225 + test_KErrNone(nRes);
1.226 +
1.227 +
1.228 + //-- create write buffer 2
1.229 + if(gWindowsNum == 2)
1.230 + {
1.231 + nRes=gWriteBuffer2.CreateMax(gWriteBufSize2);
1.232 + test_KErrNone(nRes);
1.233 + }
1.234 +
1.235 + return ETrue;
1.236 +}
1.237 +
1.238 +//---------------------------------------------------------------------------------
1.239 +
1.240 +/** Finalise environment */
1.241 +void Finalise(void)
1.242 +{
1.243 + BusLocalDrv.Disconnect();
1.244 + BusLocalDrv.Close();
1.245 +
1.246 + gWriteBuffer1.Close();
1.247 + gWriteBuffer2.Close();
1.248 +
1.249 + Fs.Close();
1.250 +}
1.251 +
1.252 +
1.253 +/**
1.254 + Just a helper method. Looks for a given pattern in the given string and returns the rest of the found token.
1.255 + @return KErrNotFound if the aPattern wasn't found in aSrc
1.256 + KErrNone otherwise and the rest of the token in aToken
1.257 +*/
1.258 +TInt DoFindToken(const TDesC& aSrc, const TDesC& aPattern,TPtrC& aToken)
1.259 +{
1.260 + TLex lex(aSrc);
1.261 + TPtrC token;
1.262 +
1.263 + for(;;)
1.264 + {
1.265 + lex.SkipSpace();
1.266 + token.Set(lex.NextToken());
1.267 +
1.268 + if(token.Length() == 0)
1.269 + {
1.270 + test.Printf(_L("Parameter %S not found!\n"), &aPattern);
1.271 + return KErrNotFound;
1.272 + }
1.273 +
1.274 + if(token.FindF(aPattern) == 0)
1.275 + {//-- found a requires patern, extract substring next to it
1.276 + aToken.Set(token.Right(token.Length() - aPattern.Length()));
1.277 + break;
1.278 + }
1.279 +
1.280 +
1.281 + }
1.282 +
1.283 + return KErrNone;
1.284 +}
1.285 +
1.286 +
1.287 +/**
1.288 + Parse the command line, which shall look like:
1.289 + drv=[0..25] pos=xxx:yyy [wrep=<number>] wn=[1,2] w1sz=<number> w1pi=<number> [w2sz=<number> w2pi=<number>]
1.290 +*/
1.291 +TBool ParseCommandLine(void)
1.292 +{
1.293 + TBuf<0x100> cmdLine;
1.294 + User::CommandLine(cmdLine);
1.295 +
1.296 + cmdLine.LowerCase();
1.297 +
1.298 + test.Printf(_L("Command line:\n"));
1.299 + test.Printf(cmdLine);
1.300 + test.Printf(_L("\n"));
1.301 +
1.302 + TLex lexParam;
1.303 +
1.304 + TInt nVal;
1.305 + TUint uVal;
1.306 + TInt nRes;
1.307 +
1.308 + TPtrC token;
1.309 +
1.310 + //-- process "drv" parameter. It shall look like: "drv=1"
1.311 + //-- this is a physical number of a local drive
1.312 + if(DoFindToken(cmdLine, _L("drv="), token) != KErrNone)
1.313 + return EFalse;
1.314 +
1.315 + lexParam.Assign(token);
1.316 + lexParam.SkipSpace();
1.317 + nRes = lexParam.Val(nVal);
1.318 + if(nRes!= KErrNone || nVal < EDriveA || nVal > EDriveZ)
1.319 + {
1.320 + test.Printf(_L("Invalid 'drv' parameter value!\n"));
1.321 + return EFalse;
1.322 + }
1.323 +
1.324 + gLocalDrvNum = nVal;
1.325 +
1.326 +
1.327 + //-- process "pos" parameter It shall look like: "pos=xxx:yyy" where "xxx" is a start media position, "yyy" end media position
1.328 + //-- It specifies start and end media position
1.329 + if(DoFindToken(cmdLine, _L("pos="), token) != KErrNone)
1.330 + return EFalse;
1.331 +
1.332 + lexParam.Assign(token);
1.333 + lexParam.SkipSpace();
1.334 +
1.335 + TInt64 startPos;
1.336 + TInt64 endPos;
1.337 +
1.338 + //-- start media position
1.339 + nRes = lexParam.Val(startPos);
1.340 + if(nRes!= KErrNone || startPos< 0)
1.341 + {
1.342 + test.Printf(_L("invalid start 'pos' value!\n"));
1.343 + return EFalse;
1.344 + }
1.345 +
1.346 + //-- delimiter
1.347 + lexParam.SkipSpace();
1.348 + if(lexParam.Get() != ':')
1.349 + {
1.350 + test.Printf(_L("invalid 'pos' parameter!\n"));
1.351 + return EFalse;
1.352 + }
1.353 +
1.354 + //-- end media position
1.355 + lexParam.SkipSpace();
1.356 + nRes = lexParam.Val(endPos);
1.357 + if(nRes!= KErrNone || endPos < 0)
1.358 + {
1.359 + test.Printf(_L("invalid end 'pos' value!\n"));
1.360 + return EFalse;
1.361 + }
1.362 +
1.363 + gMediaStartPos = startPos;
1.364 + gMediaEndPos = endPos;
1.365 +
1.366 +
1.367 + //-- process "wn" parameter It shall look like: "wn=1" or "wn=2"
1.368 + //-- It specifies number of sliding windows.
1.369 + lexParam.SkipSpace();
1.370 + if(DoFindToken(cmdLine, _L("wn="), token) != KErrNone)
1.371 + return EFalse;
1.372 +
1.373 + lexParam.Assign(token);
1.374 + lexParam.SkipSpace();
1.375 +
1.376 + nRes = lexParam.Val(uVal);
1.377 + if(nRes!= KErrNone || uVal > 2)
1.378 + {
1.379 + test.Printf(_L("wrong 'wn' parameter value, it must be 1 or 2 !\n"));
1.380 + return EFalse;
1.381 + }
1.382 +
1.383 + gWindowsNum = uVal;
1.384 +
1.385 +
1.386 + //-- process "w1sz" & "w1pi" parameters. They shall look like: "w1sz=16384" & "w1pi=512"
1.387 + //-- these parameters specify size and position increment for the window 1
1.388 + //-- if w1pi <0 the window will slide from the media end position to the beginning
1.389 + lexParam.SkipSpace();
1.390 + if(DoFindToken(cmdLine, _L("w1sz="), token) != KErrNone)
1.391 + return EFalse;
1.392 +
1.393 + lexParam.Assign(token);
1.394 + lexParam.SkipSpace();
1.395 +
1.396 + nRes = lexParam.Val(uVal);
1.397 + if(nRes!= KErrNone || uVal ==0)
1.398 + {
1.399 + test.Printf(_L("wrong 'w1sz' parameter value, it must be > 0 !\n"));
1.400 + return EFalse;
1.401 + }
1.402 +
1.403 + gWriteBufSize1 = uVal;
1.404 +
1.405 +
1.406 + lexParam.SkipSpace();
1.407 + if(DoFindToken(cmdLine, _L("w1pi="), token) != KErrNone)
1.408 + return EFalse;
1.409 +
1.410 + lexParam.Assign(token);
1.411 + lexParam.SkipSpace();
1.412 +
1.413 + nRes = lexParam.Val(nVal);
1.414 + if(nRes!= KErrNone)
1.415 + {
1.416 + return EFalse;
1.417 + }
1.418 +
1.419 + gWriteGranularity1 = nVal;
1.420 +
1.421 + //-- process "w2sz" & "w2pi" parameters. They shall look like: "w2sz=16384" & "w2pi=512"
1.422 + //-- these parameters specify size and position increment for the window 1
1.423 + //-- if w1pi <0 the window will slide from the media end position to the beginning
1.424 + if(gWindowsNum == 2)
1.425 + {
1.426 + lexParam.SkipSpace();
1.427 + if(DoFindToken(cmdLine, _L("w2sz="), token) != KErrNone)
1.428 + return EFalse;
1.429 +
1.430 + lexParam.Assign(token);
1.431 + lexParam.SkipSpace();
1.432 +
1.433 + nRes = lexParam.Val(uVal);
1.434 + if(nRes!= KErrNone || uVal ==0)
1.435 + {
1.436 + test.Printf(_L("wrong 'w2sz' parameter value, it must be > 0 !\n"));
1.437 + return EFalse;
1.438 + }
1.439 +
1.440 + gWriteBufSize2 = uVal;
1.441 +
1.442 +
1.443 + lexParam.SkipSpace();
1.444 + if(DoFindToken(cmdLine, _L("w2pi="), token) != KErrNone)
1.445 + return EFalse;
1.446 +
1.447 + lexParam.Assign(token);
1.448 + lexParam.SkipSpace();
1.449 +
1.450 + nRes = lexParam.Val(nVal);
1.451 + if(nRes!= KErrNone)
1.452 + {
1.453 + return EFalse;
1.454 + }
1.455 +
1.456 + gWriteGranularity2 = nVal;
1.457 + }
1.458 +
1.459 + //-- extract wrep=<number> parameter.
1.460 + //-- it specifies how many times buffers will be written to the media
1.461 + lexParam.SkipSpace();
1.462 + if(DoFindToken(cmdLine, _L("wrep="), token) == KErrNone)
1.463 + {
1.464 +
1.465 +
1.466 + lexParam.Assign(token);
1.467 + lexParam.SkipSpace();
1.468 +
1.469 + nRes = lexParam.Val(uVal);
1.470 + if(nRes!= KErrNone || uVal ==0 )
1.471 + {
1.472 + test.Printf(_L("wrong 'wrep' parameter value, it must be >0 !\n"));
1.473 + return EFalse;
1.474 + }
1.475 +
1.476 + gNumWrites = uVal;
1.477 + }
1.478 + else
1.479 + {
1.480 + gNumWrites = 1;
1.481 + }
1.482 +
1.483 +
1.484 + return ETrue;
1.485 +}
1.486 +
1.487 +void PrintInfo()
1.488 +{
1.489 + test.Printf(_L("Media write benchmark test. For use mostly with mmc/sd cards.\n"));
1.490 + test.Printf(_L("Usage: See source code for command line parameters.\n"));
1.491 +}
1.492 +
1.493 +
1.494 +//---------------------------------------------------------------------------------
1.495 +
1.496 +void MainL(void)
1.497 +{
1.498 + test.Title();
1.499 + test.Start(_L("Start testing...\n"));
1.500 +
1.501 +
1.502 + //-- it will initialise global test parameters
1.503 + if(!ParseCommandLine())
1.504 + {
1.505 + PrintInfo();
1.506 + return;
1.507 + }
1.508 +
1.509 + if(!Initialise())
1.510 + {
1.511 + return; //-- something went wrong
1.512 + }
1.513 +
1.514 +
1.515 + DoWriteBMTest();
1.516 +
1.517 + Finalise();
1.518 +
1.519 + test.End();
1.520 +}
1.521 +
1.522 +
1.523 +TInt E32Main()
1.524 +{
1.525 +
1.526 + CTrapCleanup* cleanup=CTrapCleanup::New() ; // get clean-up stack
1.527 +
1.528 + TRAPD(r,MainL());
1.529 +
1.530 + delete cleanup ; // destroy clean-up stack
1.531 +
1.532 + return r;
1.533 +}
1.534 +
1.535 +
1.536 +