Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// Copyright (c) 2006-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:
// f32test\bench\t_benchmain.cpp
//
//
#include <f32file.h>
#include <e32test.h>
#include <e32hal.h>
#include <e32math.h>
#include <f32dbg.h>
#include "t_benchmain.h"
#include "t_chlffs.h"
RFs TheFs;
TFileName gSessionPath;
TFileName gExeFileName(RProcess().FileName());
TInt gAllocFailOff=KAllocFailureOff;
TInt gAllocFailOn=KAllocFailureOff;
TInt64 gSeed = 51703;
TInt gFilesLimit;
TInt gTypes;
TInt gMode;
TInt gFormat = EFalse;
TInt gMinutes;
TInt gFileSize = 0; // In Kbytes
TInt gTestHarness = 0;
TInt gTestCase = 1;
TInt gTimeUnit = 1000; // values: 1 - us, 1000 - ms, 1000000 - s
TChar gDriveToTest = ' ';
////////////////////////////////////////////////////////////
// Template functions encapsulating ControlIo magic
//
template <class C>
TInt controlIo(RFs &fs, TInt drv, TInt fkn, C &c)
{
TPtr8 ptrC((TUint8 *)&c, sizeof(C), sizeof(C));
TInt r = fs.ControlIo(drv, fkn, ptrC);
return r;
}
/** Prints headers of FAT32 and File Cache benchmarking
@param aType type of test (FAT32 = 1/2 or File Cache = 3/4/5)
@param
*/
void PrintHeaders(TInt aType, TPtrC16 aTitle )
{
TBuf16<250> title = _L("#~TestTitle_%d: ");
title.Append(aTitle);
title.Append(_L("\n"));
test.Printf(_L("#~TestId=%d\n"), gTestHarness);
test.Printf(title, gTestHarness);
test.Printf(_L("#~Report Variant: \n"));
test.Printf(_L("#~Report Description: \n"));
_LIT(KSeconds,"seconds");
_LIT(KMilliSecs,"milliseconds");
_LIT(KMicroSecs,"microseconds");
TPtrC16 timeUnit;
if (gTimeUnit == 1)
timeUnit.Set(KMicroSecs);
else if (gTimeUnit == 1000)
timeUnit.Set(KMilliSecs);
else if (gTimeUnit == 1000000)
timeUnit.Set(KSeconds);
else
{
test.Printf(_L("Please, check gTimeUnit value\n"));
test(EFalse);
}
if(aType == 1)
{ // All FAT32 tests but t_fsrrepeat
test.Printf(_L("#~TestParam_%d: MaxFiles=%d, type=%d, mode=%d, timeUnit=%S\n"), gTestHarness, gFilesLimit, gTypes, gMode, &timeUnit);
test.Printf(_L("#~TestRows_%d: 4\n"), gTestHarness);
test.Printf(_L("#~TestColumns_%d: 4, NFiles, 8_3, 20_chars, 50_50\n"), gTestHarness);
}
else if(aType == 2)
{ // t_fsrrepeat
test.Printf(_L("#~TestParam_%d: MaxFiles=%d, type=%d, mode=%d, timeUnit=%S\n"), gTestHarness, gFilesLimit, gTypes, gMode, &timeUnit);
test.Printf(_L("#~TestRows_%d: 12\n"), gTestHarness);
test.Printf(_L("#~TestColumns_%d: 4, DirName, 1st, 2nd, 3rd\n"), gTestHarness);
}
else if(aType == 3)
{ // Large sequential reads/writes
test.Printf(_L("#~TestParam_%d: mode=%d, timeUnit=%S\n"), gTestHarness, gMode, &timeUnit);
test.Printf(_L("#~TestRows_%d: 8\n"), gTestHarness);
test.Printf(_L("#~TestColumns_%d: 4, bsize, 100KB, 1MB, 10MB\n"), gTestHarness);
}
else if(aType == 4)
{ // Small random reads/writes
test.Printf(_L("#~TestParam_%d: mode=%d, timeUnit=%S\n"), gTestHarness, gMode, &timeUnit);
test.Printf(_L("#~TestRows_%d: 11\n"), gTestHarness);
test.Printf(_L("#~TestColumns_%d: 8, bsize, 1KB, 2KB, 4KB, 8KB, 16KB, 32KB, 64KB\n"), gTestHarness);
}
else if(aType == 5)
{ // Streaming
test.Printf(_L("#~TestParam_%d: mode=%d, timeUnit=%S\n"), gTestHarness, gMode, &timeUnit);
test.Printf(_L("#~TestRows_%d: 6\n"), gTestHarness);
test.Printf(_L("#~TestColumns_%d: 4, bsize, 5m_w, 15s_w_r, 15s_w_r \n"), gTestHarness);
}
else
{
test.Printf(_L("Check the function PrintHeaders() in t_benchmain.cpp, which wasn't called with the right parameters\n"));
test(EFalse);
}
}
/** Prints a line of results
@param aPosX Row of the table
@param aPosY Column of the table
@param aValue Value figure for that position
*/
void PrintResultTime( TInt aPosX, TInt aPosY, TInt aValue)
{
test.Printf(_L("#~TS_Res_%d,%d,[%d,%d]=%d\n "), gTestHarness, gTestCase, aPosX, aPosY, aValue );
}
/** Prints any other type of data
@param aPosX Row of the table
@param aPosY Column of the table
@param aValue Value figure for that position
*/
void PrintResult( TInt aPosX, TInt aPosY, TInt aValue)
{
test.Printf(_L("#~TS_Res_%d,%d,[%d,%d]=%d\n "), gTestHarness, gTestCase, aPosX, aPosY, aValue);
}
/** Prints string
@param aPosX Row of the table
@param aPosY Column of the table
@param aValue Value figure for that position
*/
void PrintResultS( TInt aPosX, TInt aPosY, TDes16& aValue)
{
TBuf16<250> buffer = _L("#~TS_Res_%d,%d,[%d,%d]=");
buffer.Append(aValue);
buffer.Append(_L("\n"));
test.Printf(buffer, gTestHarness, gTestCase, aPosX, aPosY);
}
/** Call all RFormat methods
@param aDrive Drive to be formatted
*/
void FormatFat(TDriveUnit aDrive)
{
RFormat format;
TPckgBuf<TInt> count;
TInt r = format.Open(TheFs, aDrive.Name(), EQuickFormat, count());
FailIfError(r);
test(count() == 100);
TRequestStatus status;
while (count())
{
format.Next(count, status);
User::WaitForRequest(status);
test(status == KErrNone || status == KErrNotSupported);
}
format.Close();
test.Printf(_L("Drive formatted\n"));
}
/** Validates the drive selection
@param aDrive Drive to be validated
@param aTest Type of test
*/
TInt ValidateDriveSelection(TDriveUnit aDrive,TSelectedTest aTest)
{
if ((aDrive == EDriveZ) || ((aDrive == EDriveC) && (aTest == ELocalDriveTest)))
{
test.Printf(_L("Test not available for this drive\n"));
test.Printf(_L("Press any key to continue...\n"));
return (KErrNotSupported);
}
else
return (KErrNone);
}
/** Validates the selection for this tests and update appropriate variables
@param aSelector This object is meant to give information about what needs
to be tests in manual mode
*/
TInt Validate(TAny* aSelector)
{
if(gMode == 0)
{
if (((CSelectionBox*)aSelector)->CurrentKeyPress() != EKeyEnter)
return(KErrNone);
TInt r = ValidateDriveSelection(((CSelectionBox*)aSelector)->CurrentDrive(),EFileSeekTest);
if (r == KErrNotSupported)
return (r);
TDriveUnit drive = ((CSelectionBox*)aSelector)->CurrentDrive();
gSessionPath[0] = TUint8('A' + drive);
r = TheFs.SetSessionPath(gSessionPath);
FailIfError(r);
}
return KErrNone;
}
/** Prints current volume information
*/
void PrintVolInfo()
{
TVolumeInfo volInfo;
TInt r;
r = TheFs.Volume(volInfo);
FailIfError(r);
test.Printf(_L("DriveAtt:0x%X, MediaAtt:0x%X, Free:%d KBytes\n"), volInfo.iDrive.iDriveAtt, volInfo.iDrive.iMediaAtt, (TUint32)(volInfo.iFree / 1024));
}
/** Create directory with a number of files, with specified file name type
@param aN number of files to create
@param aType file names type : 1 - 8.3, 2 - 20 characters, 3 - 50/50
*/
TInt CreateDirWithNFiles(TInt aN, TInt aType)
{
TInt i,r=0;
RFile file;
TBuf16<50> directory;
TBuf16<50> dirtemp;
TBuf16<50> path;
TBuf16<50> buffer(50);
dirtemp.Format(KDirMultipleName,aType, aN);
directory=gSessionPath;
directory.Append(dirtemp);
r = TheFs.MkDir(directory);
test(r == KErrNone || r == KErrAlreadyExists);
const TUint KNumFilesPrintTreshold = 100;
const TInt KFileSize = gFileSize * 1024;
PrintVolInfo();
i = 0;
while( i < aN )
{
// generate file name depending on type required
switch(aType)
{
case 1: // 8.3 filemnames
FileNamesGeneration(buffer, 8, i, i%3+1);
break;
case 2: // 20 characrer filenames
FileNamesGeneration(buffer, 20, i, i%3+1);
break;
case 3: // 50/50 mix
if(i%2)
FileNamesGeneration(buffer, 8, i, i%3+1) ;
else
FileNamesGeneration(buffer, 20, i, i%3+1) ;
break;
default:
test(0);
break;
};
path = directory;
path.Append(buffer);
// create or replace a file
r = file.Replace(TheFs, path, EFileShareAny|EFileWrite);
if(r != KErrNone)
{
PrintVolInfo();
test.Printf(_L("Error creating file: %S, %d\n"), &path, r);
test(0);
}
// set file size if required, file contents doesn't matter
if(gFileSize > 0)
{
r = file.SetSize(KFileSize);
if(r != KErrNone)
{
PrintVolInfo();
test.Printf(_L("Error setting file size: %S, %d, err:%d\n"), &path, KFileSize, r);
test(0);
}
}
file.Close();
if(i > 0 && ((i+1)%KNumFilesPrintTreshold) == 0)
{
test.Printf(_L("created %d files, type:%d\n"), i + 1, aType);
}
i++;
}//while
// write "last.txt" file to the end of directory
path = directory;
path.Append(KCommonFile);
r = file.Replace(TheFs,path,EFileShareAny|EFileWrite);
if(r != KErrNone)
{
PrintVolInfo();
test.Printf(_L("Error creating file: %S, %d\n"), &path, r);
test(0);
}
// put random content to the "last.txt" file if specified length of files > 0
if(gFileSize > 0)
{
r = file.SetSize(gFileSize * 1024); // gFileSize is in KBytes
if(r != KErrNone)
{
PrintVolInfo();
test.Printf(_L("Error setting file size: %S, %d\n"), &path, r);
test(0);
}
}
file.Close();
return(KErrNone);
}
/**
Creates 12 directories with different sort of files and namefiles
100 files with 8.3, 20 chars and 50/50
1000 files with 8.3, 20 chars and 50/50
5000 files with 8.3, 20 chars and 50/50
10000 files with 8.3, 20 chars and 50/50
*/
TInt TestFileCreate(TAny* aSelector)
{
TInt i = 100, j = 1;
Validate(aSelector);
while(i <= gFilesLimit)
{
if(i == 100)
{
j = 1;
while(j <= gTypes)
CreateDirWithNFiles(100, j++);
}
if(i == 1000)
{
j=1;
while(j <= gTypes)
CreateDirWithNFiles(1000, j++);
}
if(i == 5000)
{
j = 1;
while(j <= gTypes)
CreateDirWithNFiles(5000, j++);
}
if(i == 10000)
{
j = 1;
while(j <= gTypes)
CreateDirWithNFiles(10000, j++);
}
i += 100;
}
return(KErrNone);
}
/** Generate a filename according to the parameters configuration
@param aBuffer Buffer where the name of the file will be returned
@param aLong Length of the name of the file
@param aPos Number to be attached to the name of the file
@param ext Type of extension (1/2/3)
*/
void FileNamesGeneration(TDes16& aBuffer, TInt aLong, TInt aPos,TInt ext)
{
TInt padding;
TInt i=0;
TBuf16<10> tempbuf;
_LIT(KNumber,"%d");
tempbuf.Format(KNumber, aPos);
padding = aLong - tempbuf.Size() / 2;
aBuffer = _L("");
while(i < padding)
{
aBuffer.Append('F');
i++;
}
_LIT(KExtension1, ".TXT");
_LIT(KExtension2, ".HTM");
_LIT(KExtension3, ".LOG");
aBuffer.Append(tempbuf);
switch(ext)
{
case 1: aBuffer.Append(KExtension1);break;
case 2: aBuffer.Append(KExtension2);break;
case 3: aBuffer.Append(KExtension3);break;
default: aBuffer.Append(KExtension1);break;
}
}
/** Do a checkdisk and report failure
*/
void CheckDisk()
{
test.Next(_L("Check Disk"));
TInt r = TheFs.CheckDisk(gSessionPath);
if (r != KErrNone && r != KErrNotSupported && r != KErrPermissionDenied)
ReportCheckDiskFailure(r);
}
/** Report a disk failure
@param aRet The error will be returned in this variable
*/
void ReportCheckDiskFailure(TInt aRet)
{
test.Printf(_L("CHECKDISK FAILED: "));
switch(aRet)
{
case 1: test.Printf(_L("File cluster chain contains a bad value (<2 or >maxCluster)\n")); break;
case 2: test.Printf(_L("Two files are linked to the same cluster\n")); break;
case 3: test.Printf(_L("Unallocated cluster contains a value != 0\n")); break;
case 4: test.Printf(_L("Size of file != number of clusters in chain\n")); break;
default: test.Printf(_L("Undefined Error value %d\n"),aRet);
}
}
/** Expand the cleanup stack
*/
void PushLotsL()
{
TInt i;
for(i=0;i<1000;i++)
CleanupStack::PushL((CBase*)NULL);
CleanupStack::Pop(1000);
}
/** Do testing on aDrive
@param aDrive Drive for the testing
*/
void DoTests(TInt aDrive)
{
gSessionPath=_L("?:\\");
TChar driveLetter;
TInt r = TheFs.DriveToChar(aDrive, driveLetter);
FailIfError(r);
gSessionPath[0] = (TText)driveLetter;
r = TheFs.SetSessionPath(gSessionPath);
FailIfError(r);
test.Printf(_L("DoTests() Session Path: %S\n"),&gSessionPath);
CheckMountLFFS(TheFs,driveLetter);
User::After(1000000);
r = TheFs.MkDirAll(gSessionPath);
if (r != KErrNone && r != KErrAlreadyExists)
{
test.Printf(_L("MkDirAll() r %d\n"),r);
test(EFalse);
}
TheFs.ResourceCountMarkStart();
TRAP(r,CallTestsL());
if (r == KErrNone)
TheFs.ResourceCountMarkEnd();
else
{
test.Printf(_L("Error: Leave %d\n"),r);
test(EFalse);
}
CheckDisk();
}
/** Syntax of the test
@param aOption option 1 is related to FAT32 testing/option 2 relates to the file caching
*/
void syntax (TInt aOption)
{
_LIT(KBad, "Wrong argument");
if(aOption == 1)
{
test.Printf(_L("Usage: \n testname <drive> <100/1000/5000/10000 number of files> <1/2/3 type of files> <mode 0 manual, 1 automatic>\n "));
}
else if (aOption == 2)
{
test.Printf(_L("Usage: \n t_fcachebm <drive> <mode 0 manual, 1 automatic>\n "));
}
User::Panic(KBad,KErrArgument);
}
/**
Parse commands :
1) t_name drive maxfiles filetypes manual/automatic
maxfiles can be: 100, 1000, 5000 or 10000
filetypes can be 1 for 8.3, 2 for 20 chars as well and 3 for all
manual 0 and automatic 1
2) t_fcachebm drive manua/automatic
3) t_fsrcreatefiles
*/
void ParseCommandArguments()
{
TBuf<0x100> cmd;
User::CommandLine(cmd);
test.Printf(_L("Command line:\n"));
test.Printf(cmd);
test.Printf(_L("\n"));
TLex lex(cmd);
lex.SkipSpace();
TPtrC token;
TFileName thisfile=RProcess().FileName();
TInt i = 0;
TInt testcase = 0;
TBool finish = EFalse;
_LIT(KCacheBM, "Z:\\sys\\bin\\t_fcachebm.exe");
_LIT(KCreate, "Z:\\sys\\bin\\t_fsrcreatefiles.exe");
test.Printf(KCacheBM);
test.Printf(thisfile);
while((!finish) && (i <= 5))
{
switch(i)
{
case 0:
if((thisfile != KCacheBM) && (thisfile != KCreate)) // FAT32 tests
testcase = 1;
else if(thisfile == KCreate) // FAT32 test files creation
testcase = 3;
else // File Cache (PREQ914) performance tests
testcase = 2;
break;
case 1:
test.Printf(_L("\nCLP=%S\n"), &token);
if(token.Length() != 0)
{
gDriveToTest = token[0];
gDriveToTest.UpperCase();
if(gMode==1)
gSessionPath[0] = (TText)gDriveToTest;
}
else
{
gDriveToTest = 'C';
}
break;
case 2:
if((testcase == 1) || (testcase == 3)) // testcase == 1 || testcase == 3
{
if(token.Length() != 0)
{
test.Printf(_L("Number of files=%S\n"),&token);
if(token[0]=='5')
{
gFilesLimit = 5000;
}
else
if(token[0] == '1' && token.Length() == 3) gFilesLimit = 100;
else if(token[0] == '1' && token.Length() == 4) gFilesLimit = 1000;
else if(token[0] == '1' && token.Length() == 5) gFilesLimit = 10000;
else syntax(testcase);
}
else
gFilesLimit = 10000 ;
}
else // (testcase == 2)
{
if(token.Length() == 1)
{
TChar c = token[0];
test.Printf(_L("0 manual/1 automatic ? %S\n"),&token);
if(c.IsDigit() && ((c == '0') || (c == '1')))
gMode = c.GetNumericValue();
else syntax(testcase);
}
else
syntax(testcase);
}
break;
case 3:
if((testcase == 1) || (testcase == 3))
{
if(token.Length() == 1)
{
TChar c = token[0];
test.Printf(_L("File type=%S\n"), &token);
if(c.IsDigit() &&((c == '1') || (c == '2') || (c == '3')))
gTypes = c.GetNumericValue();
else syntax(testcase);
}
else // Default value
gTypes = 3;
}
break;
case 4:
if((testcase == 1) || (testcase == 3))
{
TChar c = token[0];
if(token.Length() == 1)
{
test.Printf(_L("0 manual/1 automatic ? %S\n"),&token);
if(c.IsDigit() && ((c == '0') || (c == '1')))
gMode = c.GetNumericValue();
else syntax(1);
}
else
gMode = 0;
}
break;
case 5:
if(testcase == 3)
{
TChar c = token[0];
if(c.IsDigit())
gFileSize = c.GetNumericValue();
else syntax(1);
}
break;
default:
syntax(testcase);
}
finish = lex.Eos();
token.Set(lex.NextToken());
i++;
}
}
/** Main function
@return KErrNone if everything was ok, panics otherwise
*/
TInt E32Main()
{
CTrapCleanup* cleanup;
cleanup = CTrapCleanup::New();
TRAPD(r,PushLotsL());
__UHEAP_MARK;
test.Title();
test.Start(_L("Starting benchmarking tests..."));
ParseCommandArguments(); //need this for drive letter to test and all the parameters
r = TheFs.Connect();
FailIfError(r);
TheFs.SetAllocFailure(gAllocFailOn);
TTime timerC;
timerC.HomeTime();
TFileName sessionp;
TheFs.SessionPath(sessionp);
TInt theDrive;
r = TheFs.CharToDrive(gDriveToTest,theDrive);
FailIfError(r);
PrintDrvInfo(TheFs, theDrive);
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
TPckgBuf<TIOCacheValues> pkgOrgValues;
TIOCacheValues& orgValues=pkgOrgValues();
r = controlIo(TheFs,theDrive, KControlIoCacheCount, orgValues);
FailIfError(r);
test.Printf(_L("\nNumber of items on close list at beginning=%d\n"), orgValues.iCloseCount);
test.Printf(_L("Number of items on free list at beginning=%d\n"), orgValues.iFreeCount);
test.Printf(_L("Number of items allocated at beginning=%d\n"), orgValues.iAllocated);
#endif
DoTests(theDrive);
TTime endTimeC;
endTimeC.HomeTime();
TTimeIntervalSeconds timeTakenC;
r = endTimeC.SecondsFrom(timerC,timeTakenC);
FailIfError(r);
if(gFormat)
{
FormatFat(gSessionPath[0]-'A');
}
test.Printf(_L("#~T_Timing_%d: %d S\n"), gTestHarness, timeTakenC.Int());
TheFs.SetAllocFailure(gAllocFailOff);
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
TPckgBuf<TIOCacheValues> pkgValues;
TIOCacheValues& values=pkgValues();
r = controlIo(TheFs,theDrive, KControlIoCacheCount, values);
test(r==KErrNone);
test.Printf(_L("\nNumber of items on close list at end=%d\n"),values.iCloseCount);
test.Printf(_L("Number of items on free list at end=%d\n"),values.iFreeCount);
test.Printf(_L("Number of items allocated at the end=%d\n"),values.iAllocated);
test(orgValues.iCloseCount==values.iCloseCount);
test(orgValues.iAllocated == values.iAllocated);
#endif
TheFs.Close();
test.End();
test.Close();
__UHEAP_MARKEND;
delete cleanup;
return(KErrNone);
}