--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/pccd/t_med_writebm.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,533 @@
+// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\pccd\t_med_writebm.cpp
+//
+//
+
+/**
+ @file
+*/
+
+#define __E32TEST_EXTENSION__
+
+#include <e32test.h>
+#include <f32fsys.h>
+#include <e32math.h>
+
+/*
+ SD/MMC/other media benchmark test
+ Writes data to the media and prints out time taken (microseconds).
+ Works on TBusLocalDrive level. May require a script to filter the results.
+
+ Principle of operation:
+ In the simple case scenario the user specifies media start and end position in bytes,
+ write buffer size (window size), the number of write repetitions (optional) and write position increment.
+
+ The test fills buffer with random data, writes it to the media (probably several times); prints out the time taken;
+ increments or decrements window position; goto begin. Test finishes when the window slides outside specified beginning or end media position.
+
+ It more complex case we have 2 windows. It is useful for FAT emulation.
+
+ -------------------------------------------
+ Command line shall look like this:
+ drv=[0..25] pos=xxx:yyy [wrep=<number>] wn=[1,2] w1sz=<number> w1pi=<number> [w2sz=<number> w2pi=<number>]
+
+ where:
+ drv=N local drive physical number for 1st MMC slot on H2 & H4 it will be 1, see variantmediadef.h
+ pos=xxx:yyy xxx start media position, yyy end media position in bytes. The test will be writing data in the range xxx-yyy
+ wrep=N optional. Specifies how many times the window will be written to the media, just for more precise time calculation. Default is 1.
+ wn=N Number of data windows being written on the media. can be 1 or 2
+
+ w1sz=N Size of the data window #1 in bytes. Must be > 0
+ w1pi=N Media position increment for the window #1. if positive, the window will be moving from xxx to yyy (see media pos parameter);
+ if 0, the window won't change its position; if <0, the window will be moving from yyy to xxx
+
+ w2sz the same for the window #2 if it is specified
+ w2pi the same for the window #2 if it is specified
+
+ 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
+ it may run forever :)
+
+ Be careful, all information on the medium will be lost !!!
+*/
+
+RTest test(_L("MMC/SD write performance test"));
+
+TBusLocalDrive BusLocalDrv;
+RFs Fs;
+
+RBuf8 gWriteBuffer1;
+RBuf8 gWriteBuffer2;
+
+TInt gLocalDrvNum = -1; //-- LOCAL physical drive number (see Estart.txt)
+TBool gChangeFlag;
+
+TUint gWindowsNum = 0; //-- number of windows being written
+
+TUint32 gWriteBufSize1 = 0; //-- write buffer 1 size, bytes
+TInt32 gWriteGranularity1 = 0; //-- write granularity 1 (write buffer position increment)
+
+TUint32 gWriteBufSize2 = 0; //-- write buffer 2 size, bytes
+TInt32 gWriteGranularity2 = 0; //-- write granularity 2 (write buffer position increment)
+
+TInt64 gMediaStartPos = 0; //-- media start position
+TInt64 gMediaEndPos = 0; //-- media end position
+
+TUint gNumWrites = 1; //-- number of buffer writes to the media
+
+
+//---------------------------------------------------------------------------------
+
+void RndFillBuf(TDes8& aBuf);
+
+//---------------------------------------------------------------------------------
+
+/**
+ The main part of the test, actually. Writes 1 or 2 buffers to the media (possibly several times) and
+ prints out the time taken.
+*/
+void DoWriteBMTest(void)
+{
+ test.Next(_L("Performing write benchmark test.\n"));
+
+ TInt nRes;
+ TTime timeStart;
+ TTime timeEnd;
+
+ //-- if window pos increment is <0, it will move from end to the beginning position, backwards
+ TInt64 currMediaPos1 = (gWriteGranularity1 >=0) ? gMediaStartPos : gMediaEndPos-gWriteBufSize1;
+ TInt64 currMediaPos2 = (gWriteGranularity2 >=0) ? gMediaStartPos : gMediaEndPos-gWriteBufSize2;
+
+ if(gWindowsNum == 1) //-- we have only 1 window
+ {
+ currMediaPos2 = 0;
+ gWriteGranularity2 = 0;
+ }
+
+ RndFillBuf(gWriteBuffer1);
+ if(gWindowsNum == 2)
+ RndFillBuf(gWriteBuffer2);
+
+ for(;;)
+ {
+ if(currMediaPos1 <0 || (currMediaPos1 + gWriteBufSize1) > gMediaEndPos)
+ break;
+
+ if(currMediaPos2 <0 || (currMediaPos2 + gWriteBufSize2) > gMediaEndPos)
+ break;
+
+ timeStart.UniversalTime(); //-- take start time
+
+ for(TUint i=0; i<gNumWrites; ++i)
+ {
+ nRes = BusLocalDrv.Write(currMediaPos1, gWriteBuffer1); //-- write window 1
+ test_KErrNone(nRes);
+
+ if(gWindowsNum == 2)
+ {
+ nRes = BusLocalDrv.Write(currMediaPos2, gWriteBuffer2); //-- write window 2
+ test_KErrNone(nRes);
+ }
+ }//for(TUint i=0; i<gNumWrites; ++i)
+
+ timeEnd.UniversalTime(); //-- take end time
+
+ TTimeIntervalMicroSeconds usElapsed=timeEnd.MicroSecondsFrom(timeStart);
+ TInt64 usTaken = usElapsed.Int64()/gNumWrites;
+
+ //-- print out the result
+
+ test.Printf(_L("~#pos:%lu:%lu, time:%d us\n"), currMediaPos1, currMediaPos2, (TInt32)usTaken);
+
+ //-- move windows
+ currMediaPos1 += gWriteGranularity1;
+ currMediaPos2 += gWriteGranularity2;
+ }
+
+}
+
+
+//---------------------------------------------------------------------------------
+
+/** fill a given buffer with random bytes */
+void RndFillBuf(TDes8& aBuf)
+{
+ static TInt64 rndSeed = Math::Random();
+
+ //-- ?? optimise here ??
+ for(TInt i=0; i<aBuf.Size(); ++i)
+ {
+ aBuf[i] = (TUint8)Math::Rand(rndSeed);
+ }
+}
+
+
+//---------------------------------------------------------------------------------
+
+/** Initialise environment */
+TBool Initialise()
+{
+ //-- print out some parameters:
+ test.Printf(_L("~#Local Drive:%d\n"), gLocalDrvNum);
+ test.Printf(_L("~#MediaPos:%lu:%lu\n"), gMediaStartPos, gMediaEndPos);
+ test.Printf(_L("~#WinNum:%d\n"), gWindowsNum);
+ test.Printf(_L("~#NumWrites:%d\n"), gNumWrites);
+ test.Printf(_L("~#Window1 sz:%d, posInc:%d \n"), gWriteBufSize1, gWriteGranularity1);
+
+ if(gWindowsNum == 2)
+ {
+ test.Printf(_L("~#Window2 sz:%d, posInc:%d \n"), gWriteBufSize2, gWriteGranularity2);
+ }
+
+
+ test((gLocalDrvNum >= EDriveA) && (gLocalDrvNum <= EDriveZ));
+ test(gMediaStartPos >=0 && gMediaEndPos >gMediaStartPos);
+ test(gWindowsNum == 1 || gWindowsNum == 2);
+ test(gWriteBufSize1 > 0);
+ if(gWindowsNum == 2)
+ {
+ test(gWriteBufSize2 > 0);
+ }
+ test(gNumWrites > 0);
+
+
+ TInt nRes;
+ nRes = Fs.Connect();
+ test_KErrNone(nRes);
+
+ //-- connect to the TBusLocalDrive
+ test.Printf(_L("Connecting to the PHYSICAL drive #%d\n"), gLocalDrvNum);
+
+ nRes = BusLocalDrv.Connect(gLocalDrvNum, gChangeFlag);
+ test_KErrNone(nRes);
+
+ TLocalDriveCapsV2 info;
+ TPckg<TLocalDriveCapsV2> infoPckg(info);
+ nRes = BusLocalDrv.Caps(infoPckg);
+ test_KErrNone(nRes);
+
+ //-- create write buffer 1
+ nRes=gWriteBuffer1.CreateMax(gWriteBufSize1);
+ test_KErrNone(nRes);
+
+
+ //-- create write buffer 2
+ if(gWindowsNum == 2)
+ {
+ nRes=gWriteBuffer2.CreateMax(gWriteBufSize2);
+ test_KErrNone(nRes);
+ }
+
+ return ETrue;
+}
+
+//---------------------------------------------------------------------------------
+
+/** Finalise environment */
+void Finalise(void)
+{
+ BusLocalDrv.Disconnect();
+ BusLocalDrv.Close();
+
+ gWriteBuffer1.Close();
+ gWriteBuffer2.Close();
+
+ Fs.Close();
+}
+
+
+/**
+ Just a helper method. Looks for a given pattern in the given string and returns the rest of the found token.
+ @return KErrNotFound if the aPattern wasn't found in aSrc
+ KErrNone otherwise and the rest of the token in aToken
+*/
+TInt DoFindToken(const TDesC& aSrc, const TDesC& aPattern,TPtrC& aToken)
+{
+ TLex lex(aSrc);
+ TPtrC token;
+
+ for(;;)
+ {
+ lex.SkipSpace();
+ token.Set(lex.NextToken());
+
+ if(token.Length() == 0)
+ {
+ test.Printf(_L("Parameter %S not found!\n"), &aPattern);
+ return KErrNotFound;
+ }
+
+ if(token.FindF(aPattern) == 0)
+ {//-- found a requires patern, extract substring next to it
+ aToken.Set(token.Right(token.Length() - aPattern.Length()));
+ break;
+ }
+
+
+ }
+
+ return KErrNone;
+}
+
+
+/**
+ Parse the command line, which shall look like:
+ drv=[0..25] pos=xxx:yyy [wrep=<number>] wn=[1,2] w1sz=<number> w1pi=<number> [w2sz=<number> w2pi=<number>]
+*/
+TBool ParseCommandLine(void)
+{
+ TBuf<0x100> cmdLine;
+ User::CommandLine(cmdLine);
+
+ cmdLine.LowerCase();
+
+ test.Printf(_L("Command line:\n"));
+ test.Printf(cmdLine);
+ test.Printf(_L("\n"));
+
+ TLex lexParam;
+
+ TInt nVal;
+ TUint uVal;
+ TInt nRes;
+
+ TPtrC token;
+
+ //-- process "drv" parameter. It shall look like: "drv=1"
+ //-- this is a physical number of a local drive
+ if(DoFindToken(cmdLine, _L("drv="), token) != KErrNone)
+ return EFalse;
+
+ lexParam.Assign(token);
+ lexParam.SkipSpace();
+ nRes = lexParam.Val(nVal);
+ if(nRes!= KErrNone || nVal < EDriveA || nVal > EDriveZ)
+ {
+ test.Printf(_L("Invalid 'drv' parameter value!\n"));
+ return EFalse;
+ }
+
+ gLocalDrvNum = nVal;
+
+
+ //-- process "pos" parameter It shall look like: "pos=xxx:yyy" where "xxx" is a start media position, "yyy" end media position
+ //-- It specifies start and end media position
+ if(DoFindToken(cmdLine, _L("pos="), token) != KErrNone)
+ return EFalse;
+
+ lexParam.Assign(token);
+ lexParam.SkipSpace();
+
+ TInt64 startPos;
+ TInt64 endPos;
+
+ //-- start media position
+ nRes = lexParam.Val(startPos);
+ if(nRes!= KErrNone || startPos< 0)
+ {
+ test.Printf(_L("invalid start 'pos' value!\n"));
+ return EFalse;
+ }
+
+ //-- delimiter
+ lexParam.SkipSpace();
+ if(lexParam.Get() != ':')
+ {
+ test.Printf(_L("invalid 'pos' parameter!\n"));
+ return EFalse;
+ }
+
+ //-- end media position
+ lexParam.SkipSpace();
+ nRes = lexParam.Val(endPos);
+ if(nRes!= KErrNone || endPos < 0)
+ {
+ test.Printf(_L("invalid end 'pos' value!\n"));
+ return EFalse;
+ }
+
+ gMediaStartPos = startPos;
+ gMediaEndPos = endPos;
+
+
+ //-- process "wn" parameter It shall look like: "wn=1" or "wn=2"
+ //-- It specifies number of sliding windows.
+ lexParam.SkipSpace();
+ if(DoFindToken(cmdLine, _L("wn="), token) != KErrNone)
+ return EFalse;
+
+ lexParam.Assign(token);
+ lexParam.SkipSpace();
+
+ nRes = lexParam.Val(uVal);
+ if(nRes!= KErrNone || uVal > 2)
+ {
+ test.Printf(_L("wrong 'wn' parameter value, it must be 1 or 2 !\n"));
+ return EFalse;
+ }
+
+ gWindowsNum = uVal;
+
+
+ //-- process "w1sz" & "w1pi" parameters. They shall look like: "w1sz=16384" & "w1pi=512"
+ //-- these parameters specify size and position increment for the window 1
+ //-- if w1pi <0 the window will slide from the media end position to the beginning
+ lexParam.SkipSpace();
+ if(DoFindToken(cmdLine, _L("w1sz="), token) != KErrNone)
+ return EFalse;
+
+ lexParam.Assign(token);
+ lexParam.SkipSpace();
+
+ nRes = lexParam.Val(uVal);
+ if(nRes!= KErrNone || uVal ==0)
+ {
+ test.Printf(_L("wrong 'w1sz' parameter value, it must be > 0 !\n"));
+ return EFalse;
+ }
+
+ gWriteBufSize1 = uVal;
+
+
+ lexParam.SkipSpace();
+ if(DoFindToken(cmdLine, _L("w1pi="), token) != KErrNone)
+ return EFalse;
+
+ lexParam.Assign(token);
+ lexParam.SkipSpace();
+
+ nRes = lexParam.Val(nVal);
+ if(nRes!= KErrNone)
+ {
+ return EFalse;
+ }
+
+ gWriteGranularity1 = nVal;
+
+ //-- process "w2sz" & "w2pi" parameters. They shall look like: "w2sz=16384" & "w2pi=512"
+ //-- these parameters specify size and position increment for the window 1
+ //-- if w1pi <0 the window will slide from the media end position to the beginning
+ if(gWindowsNum == 2)
+ {
+ lexParam.SkipSpace();
+ if(DoFindToken(cmdLine, _L("w2sz="), token) != KErrNone)
+ return EFalse;
+
+ lexParam.Assign(token);
+ lexParam.SkipSpace();
+
+ nRes = lexParam.Val(uVal);
+ if(nRes!= KErrNone || uVal ==0)
+ {
+ test.Printf(_L("wrong 'w2sz' parameter value, it must be > 0 !\n"));
+ return EFalse;
+ }
+
+ gWriteBufSize2 = uVal;
+
+
+ lexParam.SkipSpace();
+ if(DoFindToken(cmdLine, _L("w2pi="), token) != KErrNone)
+ return EFalse;
+
+ lexParam.Assign(token);
+ lexParam.SkipSpace();
+
+ nRes = lexParam.Val(nVal);
+ if(nRes!= KErrNone)
+ {
+ return EFalse;
+ }
+
+ gWriteGranularity2 = nVal;
+ }
+
+ //-- extract wrep=<number> parameter.
+ //-- it specifies how many times buffers will be written to the media
+ lexParam.SkipSpace();
+ if(DoFindToken(cmdLine, _L("wrep="), token) == KErrNone)
+ {
+
+
+ lexParam.Assign(token);
+ lexParam.SkipSpace();
+
+ nRes = lexParam.Val(uVal);
+ if(nRes!= KErrNone || uVal ==0 )
+ {
+ test.Printf(_L("wrong 'wrep' parameter value, it must be >0 !\n"));
+ return EFalse;
+ }
+
+ gNumWrites = uVal;
+ }
+ else
+ {
+ gNumWrites = 1;
+ }
+
+
+ return ETrue;
+}
+
+void PrintInfo()
+{
+ test.Printf(_L("Media write benchmark test. For use mostly with mmc/sd cards.\n"));
+ test.Printf(_L("Usage: See source code for command line parameters.\n"));
+}
+
+
+//---------------------------------------------------------------------------------
+
+void MainL(void)
+{
+ test.Title();
+ test.Start(_L("Start testing...\n"));
+
+
+ //-- it will initialise global test parameters
+ if(!ParseCommandLine())
+ {
+ PrintInfo();
+ return;
+ }
+
+ if(!Initialise())
+ {
+ return; //-- something went wrong
+ }
+
+
+ DoWriteBMTest();
+
+ Finalise();
+
+ test.End();
+}
+
+
+TInt E32Main()
+{
+
+ CTrapCleanup* cleanup=CTrapCleanup::New() ; // get clean-up stack
+
+ TRAPD(r,MainL());
+
+ delete cleanup ; // destroy clean-up stack
+
+ return r;
+}
+
+
+