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_fcachebm.cpp
//
//
#include <f32file.h>
#include <e32test.h>
#include <e32math.h>
#include "t_select.h"
#include "t_benchmain.h"
//----------------------------------------------------------------------------------------------
//! @SYMTestCaseID PBASE-T_RCACHE-0192
//! @SYMTestType CIT
//! @SYMPREQ PREQ914
//! @SYMTestCaseDesc This test case is testing performance of the File Server Cache.
//! @SYMTestActions 0 setup the environment to execute the tests
//! 1 small random reads/writes
//! 2 large sequential reads/writes
//! 3 streaming test (100, 200 and 500 kbps)
//! @SYMTestExpectedResults Finishes if the system behaves as expected, panics otherwise
//! @SYMTestPriority High
//! @SYMTestStatus Implemented
//----------------------------------------------------------------------------------------------
GLDEF_D RTest test(_L("File Cache BM"));
LOCAL_D RSemaphore client;
LOCAL_D const TInt KHeapSize = 0x4000;
LOCAL_D const TInt KTobps = 1000;
LOCAL_D const TInt KByte = 8;
LOCAL_D const TInt KOneSec = 1000000; // One second in microseconds
// Tests setup
LOCAL_D const TInt KSmallRow = 11;
LOCAL_D const TInt KSmallCol = 7;
LOCAL_D const TInt KSmallThreshold = 64;
LOCAL_D const TInt KSeveralTimes = 10;
LOCAL_D const TInt KLargeRow = 19;
LOCAL_D const TInt KLargeCol = 3;
LOCAL_D TInt gCurrentSpeed = 0;
LOCAL_D TInt gCurrentBS = 0;
LOCAL_D TBuf8<4096> buf;
LOCAL_D TDriveList gDriveList;
// Concurrent thread
RThread gSpeedy;
RThread gSpeedyII;
TBuf16<25> gBaseFile;
TBuf16<25> gFileA;
TBuf16<25> gFileB;
TBuf16<25> gStreamFile;
TInt64 gMediaSize;
HBufC8* gBuf = NULL;
TPtr8 gBufReadPtr(NULL, 0);
HBufC8* gBufSec = NULL;
TPtr8 gBufWritePtr(NULL, 0);
HBufC8* gBufB = NULL;
TPtr8 gBufReadBPtr(NULL, 0);
TBool gWriting = EFalse;
LOCAL_D TInt ThreadCount=0;
enum TTestState
{
ENoThreads, // No threads
ETwoThreadsDif, // Accessing to different files
ETwoThreadsDifDif, // Accessing to different files, different blocksizes
ETwoThreadsSame // Accessing the same file
};
/** 2 ^ b
@param b Power
*/
LOCAL_C TInt Pow(TInt b)
{
return 1 << b;
}
/** Pseudo-random number generator, random enough for the purpose
@param aMax Upper limit of the number. The interval of generated numbers is [0,aMax)
*/
LOCAL_C TInt Rand(TInt aMax)
{
return (Math::Random() % aMax);
}
/** Fills a buffer with character aC, aC+1, aC+2, ..., aC+32, aC, etc
@param aBuffer Buffer to fill out
@param aLength Length to be filled with characters
@param aC Base character to fill the buffer
*/
LOCAL_C void FillBuffer(TDes8& aBuffer, TInt aLength, TChar aC)
{
test (aBuffer.MaxLength() >= aLength);
for(TInt i = 0; i < aLength; i++)
{
aBuffer.Append((i%32)+aC);
}
}
/** Send content through the RDebug for trgtest
not to hung, when the test is not writing
*/
LOCAL_C TInt noise(TAny* )
{
FOREVER
{
User::After(2147483647); // max value, 35 minutes, 47 seconds
if(!gWriting)
RDebug::Print(_L("."));
}
}
/** Delete content of directory
@param aDir Directory to be emptied
*/
LOCAL_C TInt DeleteAll(TDes16& aDir)
{
TBuf16<100> dir;
CFileMan* fMan = CFileMan::NewL(TheFs);
TInt r = 0;
dir = aDir;
dir.Append(_L("F*.*"));
r = fMan->Delete(dir);
delete fMan;
return r;
}
/** Creates a file of aSize KBytes
@param aFile File name
@param aSize Size of the file to be created
*/
LOCAL_C void CreateFile(TDes16& aFile, TInt aSize)
{
TInt r = 0;
RFile file;
r = file.Replace(TheFs, aFile, EFileShareAny|EFileWrite);
FailIfError(r);
TInt j = 0;
while(j <= aSize)
{
r = file.Write(gBufWritePtr, KOneK);
FailIfError(r);
j += KOneK;
}
file.Close();
}
/** Kills the concurrent session
*/
LOCAL_C void DoTestKill()
{
TInt r = 0;
gSpeedy.Kill(KErrNone);
FailIfError(r);
gSpeedy.Close();
gSpeedyII.Kill(KErrNone);
FailIfError(r);
gSpeedyII.Close();
}
/** Read aSize KBs from aFile file in blocks of aBlockSize bytes
@param aFile Name of the file
@param aPos Position from where the read starts within the file
@param aBlockSize Block size for the I/O operation
@param aSize
*/
LOCAL_C TInt ReadFromFile(TDes16& aFile, TInt aPos, TInt aBlockSize, TInt aSize)
{
TInt r = 0;
TTime startTime;
TTime endTime;
RFile file;
TInt j = 0;
TInt size = aSize * KOneK;
TTimeIntervalMicroSeconds timeTaken(0);
r = file.Open(TheFs,aFile,EFileShareAny|EFileRead);
FailIfError(r);
startTime.HomeTime();
r = file.Seek(ESeekStart, aPos);
FailIfError(r);
while(j <= size)
{
r = file.Read(gBufReadPtr, aBlockSize);
FailIfError(r);
j += aBlockSize;
}
endTime.HomeTime();
file.Close();
timeTaken = endTime.MicroSecondsFrom(startTime);
return I64LOW(timeTaken.Int64() / gTimeUnit);
}
/** Read aSize KBs from aFile file in blocks of aBlockSize bytes several times
@param aFile Name of the file
@param ayMax Maximum for the position
@param aBlockSize Block size for the I/O operation
@param aSize Size of the file in KB
*/
LOCAL_C TInt ReadFromFileSeveralTimes(TDes16& aFile, TInt ayMax, TInt aBlockSize, TInt aSize)
{
TInt r = 0;
TTime startTime;
TTime endTime;
RFile file;
TInt j = 0, i, pos;
TInt size = aSize * KOneK;
TTimeIntervalMicroSeconds timeTaken(0);
TInt64 time = 0;
r = file.Open(TheFs, aFile, EFileShareAny|EFileRead);
FailIfError(r);
i = 0;
while( i < KSeveralTimes )
{
pos = Rand(Pow(ayMax - 1));
startTime.HomeTime();
r = file.Seek(ESeekStart, pos);
FailIfError(r);
j = 0;
while(j <= size)
{
r = file.Read(gBufReadPtr, aBlockSize);
FailIfError(r);
j += aBlockSize;
}
endTime.HomeTime();
timeTaken = endTime.MicroSecondsFrom(startTime);
time += I64LOW(timeTaken.Int64());
i++;
}
file.Close();
return I64LOW((time / gTimeUnit) / KSeveralTimes); // Overflow not expected here, since the number is not big enough
}
/** Write aSize KBs to aFile file in blocks of aBlockSize bytes
@param aFile Name of the file
@param aPos Position from where the read starts within the file
@param aBlockSize Block size for the I/O operation
@param aSize Size of the file in KB
*/
LOCAL_C TInt WriteToFile(TDes16& aFile, TInt aPos, TInt aBlockSize, TInt aSize)
{
TInt r = 0;
TTime startTime;
TTime endTime;
RFile file;
TInt j = 0;
TInt size = aSize * KOneK;
TTimeIntervalMicroSeconds timeTaken(0);
r = file.Open(TheFs, aFile, EFileShareAny|EFileWrite);
FailIfError(r);
startTime.HomeTime();
r = file.Seek(ESeekStart, aPos);
FailIfError(r);
while(j <= size)
{
r = file.Write(gBufWritePtr, aBlockSize);
FailIfError(r);
j += aBlockSize;
}
endTime.HomeTime();
file.Close();
timeTaken = endTime.MicroSecondsFrom(startTime);
return I64LOW(timeTaken.Int64() / gTimeUnit);
}
/** Write aSize KBs to aFile file in blocks of aBlockSize bytes several times
@param aFile Name of the file
@param ayMax Maximum for the position
@param aBlockSize Block size for the I/O operation
@param aSize Size of the file in KB
*/
LOCAL_C TInt WriteToFileSeveralTimes(TDes16& aFile, TInt ayMax, TInt aBlockSize, TInt aSize)
{
TInt r = 0;
TTime startTime;
TTime endTime;
RFile file;
TInt i, j = 0, pos;
TInt size = aSize * KOneK;
TTimeIntervalMicroSeconds timeTaken(0);
TInt64 time = 0;
r = file.Open(TheFs, aFile, EFileShareAny|EFileWrite);
FailIfError(r);
i = 0;
while( i < KSeveralTimes )
{
pos = Rand(Pow(ayMax - 1));
startTime.HomeTime();
r = file.Seek(ESeekStart, pos);
FailIfError(r);
j = 0;
while(j <= size)
{
r = file.Write(gBufWritePtr, aBlockSize);
FailIfError(r);
j += aBlockSize;
}
endTime.HomeTime();
timeTaken = endTime.MicroSecondsFrom(startTime);
time += I64LOW(timeTaken.Int64());
i++;
}
file.Close();
return I64LOW((time / gTimeUnit) / KSeveralTimes); // Overflow not expected here, since the number is not big enough
}
/** Read small blocks in the gBaseFile
*/
LOCAL_C TInt ReadSmallBase(TAny* )
{
RTest test(_L("test 2"));
RFs fs;
RFile file;
TBuf8<1024> dummy(1024);
TInt blockSize = 0;
TInt randPos = 0;
TInt i = 0;
TInt r = fs.Connect();
fs.SetSessionPath(gSessionPath);
r = file.Open(fs, gBaseFile, EFileShareAny|EFileRead);
client.Signal();
FailIfError(r);
FOREVER
{
randPos = Rand(64) * KOneK ;
r = file.Seek(ESeekStart, randPos);
FailIfError(r);
blockSize = i;
r = file.Read(dummy, blockSize); // Sync operation
if(i >= 1023) i = 0;
else i++;
}
}
/** Read small blocks in gFileA
*/
LOCAL_C TInt ReadSmallA(TAny* )
{
RTest test(_L("test 2"));
RFs fs;
RFile file;
TInt blockSize = 0;
TInt randPos = 0;
TBuf8<1024> dummy(1024);
TInt i = 0;
TInt r = fs.Connect();
fs.SetSessionPath(gSessionPath);
r = file.Open(fs,gFileA,EFileShareAny|EFileRead);
client.Signal();
FailIfError(r);
FOREVER
{
randPos = Rand(64) * KOneK ;
r = file.Seek(ESeekStart, randPos);
FailIfError(r);
blockSize = i;
r = file.Read(dummy, blockSize); // Sync operation
FailIfError(r);
if(i >= 1023) i = 0;
else i++;
}
}
/** Read small blocks in gFileB
*/
LOCAL_C TInt ReadSmallB(TAny* )
{
RTest test(_L("test 2"));
RFs fs;
RFile file;
TBuf8<1024> dummy(1024);
TInt blockSize = 0;
TInt randPos = 0;
TInt i = 0;
TInt r = fs.Connect();
fs.SetSessionPath(gSessionPath);
r = file.Open(fs, gFileB, EFileShareAny|EFileRead);
client.Signal();
FailIfError(r);
FOREVER
{
randPos = Rand(64) * KOneK ;
r = file.Seek(ESeekStart, randPos);
FailIfError(r);
blockSize = i;
r = file.Read(dummy, blockSize); // Sync operation
FailIfError(r);
if(i >= 1023) i = 0;
else i++;
}
}
/** Read large blocks in gBaseFile
*/
LOCAL_C TInt ReadLargeBase(TAny* )
{
RTest test(_L("test 2"));
RFs fs;
RFile file;
TInt pos = 0;
TInt blockSize = 128 * KOneK;
TInt r = fs.Connect();
fs.SetSessionPath(gSessionPath);
r = file.Open(fs,gBaseFile,EFileShareAny|EFileRead);
client.Signal();
FailIfError(r);
FOREVER
{
r = file.Seek(ESeekStart, pos);
FailIfError(r);
r = file.Read(gBufReadBPtr, blockSize); // Sync operation
FailIfError(r);
}
}
/** Read large blocks in gFileA
*/
LOCAL_C TInt ReadLargeA(TAny* )
{
RTest test(_L("test 2"));
RFs fs;
RFile file;
TInt blockSize = 128 * KOneK;
TInt pos = 0;
TInt r = fs.Connect();
fs.SetSessionPath(gSessionPath);
r = file.Open(fs,gFileA,EFileShareAny|EFileRead);
client.Signal();
FailIfError(r);
FOREVER
{
r = file.Seek(ESeekStart, pos);
FailIfError(r);
r = file.Read(gBufReadBPtr, blockSize); // Sync operation
FailIfError(r);
}
}
/** Read large blocks in gFileB
*/
LOCAL_C TInt ReadLargeB(TAny* )
{
RTest test(_L("test 2"));
RFs fs;
RFile file;
TInt blockSize = 128 * KOneK;
TInt pos = 0;
TInt r=fs.Connect();
FailIfError(r);
fs.SetSessionPath(gSessionPath);
r = file.Open(fs,gFileB,EFileShareAny|EFileRead);
client.Signal();
FailIfError(r);
FOREVER
{
r = file.Seek(ESeekStart, pos);
FailIfError(r);
r = file.Read(gBufReadBPtr, blockSize); // Sync operation
FailIfError(r);
}
}
/** Small reads from a file
@param xMax Maximum position on the x axe
@param yMax Maximum position on the y axe
@param aCase Type of test. Possible values:
- ENoThreads : isolated
- ETwoThreadsSame : with two threads accessing same file
- ETwoThreadsDif : with two threads accessing dif. files
*/
LOCAL_C void smallReads(TInt xMax, TInt yMax, TTestState aCase)
{
TInt i = 0;
TInt j = 0;
TInt r = 0;
TInt timeRes = 0;
CreateFile(gBaseFile, Pow(yMax-1));
if(aCase == ETwoThreadsSame)
{ // Start two different threads accessing the same file
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
if(aCase == ETwoThreadsDif)
{ // Start two different threads accessing different files
CreateFile(gFileA, Pow(yMax-1));
CreateFile(gFileB, Pow(yMax-1));
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadSmallA, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadSmallB, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
while(i < xMax)
{ // Actual accesses and timing to the main file
j = 0;
PrintResult(i + 1, j + 1, Pow(i));
while(j < yMax)
{
if(Pow(i) < KSmallThreshold)
{
timeRes = ReadFromFile(gBaseFile, Rand(Pow(yMax - 1)), Pow(i), Pow(j));
}
else
{ // Too small for only one time measure
timeRes = ReadFromFileSeveralTimes(gBaseFile, yMax, Pow(i), Pow(j));
}
gWriting = ETrue;
User::After(1000000);
PrintResultTime(i + 1, j + 2, timeRes);
gWriting = EFalse;
j++;
}
i++;
}
if((aCase == ETwoThreadsSame) || (aCase == ETwoThreadsDif))
{ // Finish the threads
DoTestKill();
}
}
/** Large reads from a file
@param xMax Maximum position on the x axe
@param yMax Maximum position on the y axe
@param aCase Type of test. Possible values:
- ENoThreads : isolated
- ETwoThreadsSame : with two threads accessing same file
- ETwoThreadsDif : with two threads accessing dif. files
- ETwoThreadsDifDif : with two threads accessing dif. files, different block sizes (big/small)
*/
LOCAL_C void largeReads(TInt xMax, TInt yMax, TTestState aCase)
{
TInt i = 0;
TInt j = 0;
TInt r = 0;
TInt timeRes = 0;
CreateFile(gBaseFile, 10 * KOneK * KOneK); // 10 Mb
if(aCase == ETwoThreadsSame)
{ // Start two different threads accessing the same file
TRAPD(res, gBufB = HBufC8::NewL(256 * KOneK));
test(res == KErrNone && gBufB != NULL);
gBufReadBPtr.Set(gBufSec->Des());
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadLargeBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadLargeBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
if(aCase == ETwoThreadsDif)
{ // Start two different threads accessing different files
CreateFile(gFileA, KOneK * KOneK);
CreateFile(gFileB, KOneK * KOneK);
TRAPD(res, gBufB = HBufC8::NewL(256 * KOneK));
test(res == KErrNone && gBufB != NULL);
gBufReadBPtr.Set(gBufSec->Des());
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadLargeA, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadLargeB, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
if(aCase == ETwoThreadsDifDif)
{ // Start two different threads accessing different files
CreateFile(gFileA, KOneK * KOneK);
CreateFile(gFileB, KOneK * KOneK);
TRAPD(res,gBufB = HBufC8::NewL(256 * KOneK));
test(res == KErrNone && gBufB != NULL);
gBufReadBPtr.Set(gBufSec->Des());
TBuf<20> buf=_L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadLargeA, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadSmallB, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
i = 11;
while(i < xMax )
{ // Actual accesses and timing to the main file
j = 0;
PrintResult(i - 10, j + 1, Pow(i));
while(j < yMax)
{
TInt size=0;
if(j == 0) size = 100 ; // 100 Kb
if(j == 1) size = KOneK ; // 1 Mb
if(j == 2) size = 10 * KOneK ; // 10 Mb
timeRes = ReadFromFile(gBaseFile, 0, Pow(i), size);
gWriting = ETrue;
User::After(1000000);
PrintResultTime(i - 10, j + 2, timeRes);
gWriting = EFalse;
j++;
}
i++;
}
if((aCase == ETwoThreadsSame) || (aCase == ETwoThreadsDif) || (aCase == ETwoThreadsDifDif))
{ // Finish the threads
DoTestKill();
delete gBufB;
}
}
/** Large writes to a file
@param xMax Maximum position on the x axe
@param yMax Maximum position on the y axe
@param aCase Type of test. Possible values:
- ENoThreads : isolated
- ETwoThreadsSame : with two threads accessing same file
- ETwoThreadsDif : with two threads accessing dif. files
*/
LOCAL_C void largeWrites(TInt xMax, TInt yMax, TTestState aCase)
{
TInt i = 0;
TInt j = 0;
TInt r = 0;
TInt timeRes = 0;
CreateFile(gBaseFile, 10 * KOneK * KOneK); // 10 Mb
if(aCase == ETwoThreadsSame)
{ // Start two different threads accessing the same file
TRAPD(res, gBufB = HBufC8::NewL(256 * KOneK));
test(res == KErrNone && gBufB != NULL);
gBufReadBPtr.Set(gBufSec->Des());
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadLargeBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadLargeBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
if(aCase == ETwoThreadsDif)
{ // Start two different threads accessing different files
CreateFile(gFileA, KOneK * KOneK);
CreateFile(gFileB, KOneK * KOneK);
TRAPD(res, gBufB = HBufC8::NewL(256 * KOneK));
test(res == KErrNone && gBufB != NULL);
gBufReadBPtr.Set(gBufSec->Des());
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadLargeA, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadLargeB, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
i = 11;
while(i < xMax )
{ // Actual accesses and timing to the main file
j = 0;
PrintResult(i - 10 , j + 1, Pow(i));
while(j < yMax)
{
TInt size=0;
if(j == 0) size = 100 ; // 100 Kb
if(j == 1) size = KOneK ; // 1 Mb
if(j == 2) size = 10 * KOneK ; // 10 Mb
timeRes = WriteToFile(gBaseFile, 0, Pow(i), size);
gWriting = ETrue;
User::After(1000000);
PrintResultTime(i - 10, j + 2, timeRes);
gWriting = EFalse;
j++;
}
i++;
}
if((aCase == ETwoThreadsSame) || (aCase == ETwoThreadsDif) || (aCase == ETwoThreadsDifDif))
{ // Finish the threads
DoTestKill();
delete gBufB;
}
}
/** Small writes to a file
@param xMax Maximum position on the x axe
@param yMax Maximum position on the y axe
@param aCase Type of test. Possible values:
- ENoThreads : isolated
- ETwoThreadsSame : with two threads accessing same file
- ETwoThreadsDif : with two threads accessing dif. files
*/
LOCAL_C void smallWrites(TInt xMax, TInt yMax, TTestState aCase)
{
TInt i = 0;
TInt j = 0;
TInt r = 0;
TInt timeRes = 0;
CreateFile(gBaseFile, Pow(yMax-1));
if(aCase == ETwoThreadsSame)
{ // Start two different threads accessing the same file
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
if(aCase == ETwoThreadsDif)
{ // Start two different threads accessing different files
CreateFile(gFileA, Pow(yMax-1));
CreateFile(gFileB, Pow(yMax-1));
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedy.Create(buf, ReadSmallA, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
r = gSpeedyII.Create(buf, ReadSmallB, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
gSpeedyII.Resume();
client.Wait();
client.Wait();
}
while(i < xMax)
{
j = 0;
PrintResult(i + 1, j + 1, Pow(i));
while(j < yMax)
{
if(Pow(i) < KSmallThreshold)
{
timeRes = WriteToFile(gBaseFile, Rand(Pow(yMax-1)), Pow(i), Pow(j));
}
else
{
timeRes = WriteToFileSeveralTimes(gBaseFile, yMax, Pow(i), Pow(j));
}
gWriting = ETrue;
User::After(1000000);
PrintResultTime(i + 1, j + 2, timeRes);
gWriting = EFalse;
j++;
}
i++;
}
if((aCase == ETwoThreadsSame) || (aCase == ETwoThreadsDif))
{ // Finish the threads
DoTestKill();
}
}
/** This test benchmarks small random r/w (e.g. database access)
@param aSelector Selection array for manual tests
*/
LOCAL_C TInt TestSmall(TAny* aSelector)
{
Validate(aSelector);
// Each test case of the suite has an identifyer for parsing purposes of the results
gTestHarness = 7;
gTestCase = 1;
gTimeUnit = 1;
PrintHeaders(4, _L("t_fcachebm. Small Random r/w"));
// Small reads
test.Printf(_L("#~TS_Title_%d,%d: Small reads, no threads \n"), gTestHarness, gTestCase);
smallReads(KSmallRow, KSmallCol, ENoThreads);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Small reads, threads accessing same file \n"),
gTestHarness, gTestCase);
smallReads(KSmallRow, KSmallCol, ETwoThreadsSame);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Small reads, threads accessing dif files \n"),
gTestHarness, gTestCase);
smallReads(KSmallRow, KSmallCol, ETwoThreadsDif);
gTestCase++;
DeleteAll(gSessionPath);
// Small writes test case
test.Printf(_L("#~TS_Title_%d,%d: Test small writes\n"), gTestHarness, gTestCase);
smallWrites(KSmallRow, KSmallCol, ENoThreads);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Small writes, threads accessing same file \n"),
gTestHarness, gTestCase);
smallWrites(KSmallRow, KSmallCol, ETwoThreadsSame);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Small writes, threads accessing dif files \n"),
gTestHarness, gTestCase);
smallWrites(KSmallRow, KSmallCol, ETwoThreadsDif);
gTestCase++;
DeleteAll(gSessionPath);
test.Printf(_L("#~TestEnd_%d\n"), gTestHarness);
return(KErrNone);
}
/** This test benchmarks large sequential r/w (e.g. MM)
@param aSelector Selection array for manual tests
*/
LOCAL_C TInt TestLarge(TAny* aSelector)
{
Validate(aSelector);
// Each test case of the suite has an identifyer for parsing purposes of the results
gTestHarness = 8;
gTestCase = 1;
gTimeUnit = 1000;
PrintHeaders(3, _L("t_fcachebm. Large sequential r/w"));
// Large reads
test.Printf(_L("#~TS_Title_%d,%d: Large sequential reads\n"), gTestHarness, gTestCase);
largeReads(KLargeRow, KLargeCol, ENoThreads);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Large sequential reads, threads accessing same file\n"),
gTestHarness, gTestCase);
largeReads(KLargeRow, KLargeCol, ETwoThreadsSame);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Large sequential reads, threads accessing dif files\n"),
gTestHarness, gTestCase);
largeReads(KLargeRow, KLargeCol, ETwoThreadsDif);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Large sequential reads, threads accessing dif files some big some small blocks\n"),
gTestHarness, gTestCase);
largeReads(KLargeRow, KLargeCol, ETwoThreadsDifDif);
gTestCase++;
DeleteAll(gSessionPath);
// Large writings
test.Printf(_L("#~TS_Title_%d,%d: Large sequential writes\n"), gTestHarness, gTestCase);
largeWrites(KLargeRow, KLargeCol, ENoThreads);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Large sequential writes, threads accessing same file\n"),
gTestHarness, gTestCase);
largeWrites(KLargeRow, KLargeCol, ETwoThreadsSame);
gTestCase++;
test.Printf(_L("#~TS_Title_%d,%d: Large sequential writes, threads accessing dif files\n"),
gTestHarness, gTestCase);
largeWrites(KLargeRow, KLargeCol, ETwoThreadsDif);
gTestCase++;
DeleteAll(gSessionPath);
test.Printf(_L("#~TestEnd_%d\n"), gTestHarness);
return(KErrNone);
}
/** Writes aSize bytes of data in aBlockSize during aTime seconds
if the aSize bps is not met, it fails
@param f File to write to
@param aSize Size in bytes of data to be written
@param aBlockSize Block size to be used
@param aTime Time during which the write has to happen in seconds
*/
LOCAL_C TBool writeStr( RFile f, TInt aSize, TInt aBlockSize, TInt aTime)
{
TInt r = 0, j = 0;
TTime startTime, endTime;
TTimeIntervalMicroSeconds timeTaken(0);
TTimeIntervalMicroSeconds32 timeLeft(0);
TBool onTarget = ETrue;
TInt time;
TInt i = 0;
while((i < aTime) && onTarget)
{
// If measuring the CPU time
startTime.HomeTime();
j = 0;
while(j < aSize)
{
r = f.Write(gBufWritePtr, aBlockSize);
FailIfError(r);
j += aBlockSize;
}
endTime.HomeTime();
timeTaken = endTime.MicroSecondsFrom(startTime);
time = I64LOW(timeTaken.Int64());
if(time > KOneSec)
{
onTarget = EFalse;
}
timeLeft = KOneSec - time;
if(timeLeft.Int() >= 0)
{
User::After(timeLeft);
}
i++;
}
return onTarget;
}
/** Reads streaming
*/
LOCAL_C TInt ReadStream(TAny*)
{
RTest test(_L("test 2"));
RFs fs;
RFile file;
TInt j = 0;
TTime startTime, endTime;
TTimeIntervalMicroSeconds timeTaken(0);
TTimeIntervalMicroSeconds32 timeLeft(0);
TInt time;
TInt size , currentPos = 0;
TInt r = fs.Connect();
fs.SetSessionPath(gSessionPath);
r = file.Open(fs, gStreamFile, EFileShareAny|EFileRead);
client.Signal();
FailIfError(r);
r = file.Size(size);
FailIfError(r);
FOREVER
{
startTime.HomeTime();
j = 0;
while(j < (gCurrentSpeed * KOneK))
{
r=file.Read(gBufReadPtr,gCurrentBS);
FailIfError(r);
j += gCurrentBS;
}
endTime.HomeTime();
timeTaken = endTime.MicroSecondsFrom(startTime);
time = I64LOW(timeTaken.Int64());
if(time > KOneSec)
{
test.Printf(_L("Background Thread: Speed failed to be achieved: %d kbps\n"), gCurrentSpeed);
}
timeLeft = KOneSec - time;
User::After(timeLeft);
currentPos += (gCurrentSpeed * KOneK);
r = file.Size(size);
FailIfError(r);
if(currentPos > size )
{
currentPos = 0;
file.Seek(ESeekStart, currentPos);
}
}
}
/** Test case layout, read/write at aSpeed during aWtime and aRTime
@param aSpeed Target speed in kbps
@param aBlockSize Block size for the I/O operation
@param aWTime Writing time
@param aRTime Reading time
*/
LOCAL_C void streamIt ( TInt aSpeed, TInt aBlockSize, TInt aWTime, TInt aRTime, TInt aStep)
{
TInt iSize = (aSpeed * KTobps) / KByte; // Size in bytes
RFile file;
TInt pos = 0;
TInt r = 0;
PrintResult(aStep, 1, aBlockSize);
r = file.Replace(TheFs, gStreamFile, EFileShareAny|EFileWrite);
FailIfError(r);
// Streaming to the media during aWTime seconds
if(writeStr(file, iSize, aBlockSize, aWTime))
{ //Pass (1)
PrintResult(aStep, 2, 1);
}
else
{ //Fail (0)
PrintResult(aStep, 2, 0);
}
// Create a different thread for reading from the beginning during aRTime
TBuf<20> buf = _L("Speedy");
buf.AppendNum(ThreadCount++);
gCurrentSpeed = aSpeed;
gCurrentBS = aBlockSize;
r = gSpeedy.Create(buf, ReadStream, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedy.Resume();
client.Wait();
// Keep writing during the time the other thread is reading
if(writeStr(file, iSize, aBlockSize, aRTime))
{ //Pass (1)
PrintResult(aStep, 3, 1);
}
else
{ //Fail (0)
PrintResult(aStep, 3, 0);
}
// Writing from the beginning again
file.Seek(ESeekStart, pos);
if(writeStr(file, iSize, aBlockSize, aRTime))
{ //Pass (1)
PrintResult(aStep, 4, 1);
}
else
{ //Fail (0)
PrintResult(aStep, 4, 0);
}
// Kill the thread for reading
gSpeedy.Kill(KErrNone);
FailIfError(r);
gSpeedy.Close();
file.Close();
}
/** Iterating through different blocksizes
@param aSpeed Speed at which the test happens
*/
LOCAL_C void streaming(TInt aSpeed)
{
TInt i = 9; // Pow(i) = 512 bytes
TInt blockSize = 0;
TInt testStep = 1;
while( i < 15 ) // Pow(i) = 16 Kb
{
blockSize = Pow(i) ;
streamIt(aSpeed, blockSize, 5 * 60, 15, testStep++); // 5 minutes writing , then 15 secs reading
i++;
}
}
/** High level test routine. Different test cases executed
@param aSelector Test case configuration in case of manual execution
*/
LOCAL_C TInt TestStreaming(TAny* aSelector)
{
Validate(aSelector);
// Each test case of the suite has an identifyer for parsing purposes of the results
gTestHarness = 9;
gTestCase = 1;
PrintHeaders(5, _L("t_fcachebm. Streaming"));
test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 100 kbps\n"),
gTestHarness, gTestCase);
streaming(100);
test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 200 kbps\n"),
gTestHarness, ++gTestCase);
streaming(200);
test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 500 kbps\n"),
gTestHarness, ++gTestCase);
streaming(500);
DeleteAll(gSessionPath);
// Start the small random reads in the background
CreateFile(gBaseFile, Pow(KSmallCol-1));
TBuf<20> buf=_L("Speedy");
buf.AppendNum(ThreadCount++);
TInt r = gSpeedyII.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
gSpeedyII.Resume();
client.Wait();
// Measure the throughput with background activity
test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 100 kbps, while small reads\n"),
gTestHarness, ++gTestCase);
streaming(100);
test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 200 kbps, while small reads\n"),
gTestHarness, ++gTestCase);
streaming(200);
test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 500 kbps, while small reads\n"),
gTestHarness, ++gTestCase);
streaming(500);
// Kill the small random reads and writes
gSpeedyII.Kill(KErrNone);
FailIfError(r);
gSpeedyII.Close();
DeleteAll(gSessionPath);
gTestCase++;
test.Printf(_L("#~TestEnd_%d\n"), gTestHarness);
return(KErrNone);
}
/** It goes automatically through all the options
@param aSelector Configuration in case of manual execution
*/
LOCAL_C TInt TestAll(TAny* aSelector)
{
TestSmall(aSelector);
TestLarge(aSelector);
TestStreaming(aSelector);
return(KErrNone);
}
/** Call all tests
*/
GLDEF_C void CallTestsL()
{
TBuf16<25> temp;
TInt r=client.CreateLocal(0);
FailIfError(r);
// Setting up the environment and creating the needed files
gSessionPath = _L("?:\\F32-TST\\");
gSessionPath[0] = (TText) gDriveToTest;
FileNamesGeneration(temp, 8, 0, 1);
gBaseFile = gSessionPath;
gBaseFile.Append(temp);
FileNamesGeneration(temp, 8, 1, 1);
gFileA = gSessionPath;
gFileA.Append(temp);
FileNamesGeneration(temp, 8, 2, 1);
gFileB = gSessionPath;
gFileB.Append(temp);
FileNamesGeneration(temp, 8, 3, 1);
gStreamFile = gSessionPath;
gStreamFile.Append(temp);
TRAPD(res,gBuf = HBufC8::NewL(256 * KOneK));
test(res == KErrNone && gBuf != NULL);
gBufWritePtr.Set(gBuf->Des());
FillBuffer(gBufWritePtr, 256 * KOneK, 'A');
TRAPD(res2, gBufSec = HBufC8::NewL(256 * KOneK));
test(res2 == KErrNone && gBufSec != NULL);
gBufReadPtr.Set(gBufSec->Des());
TVolumeInfo volInfo;
TInt drive;
r = TheFs.CharToDrive(gDriveToTest,drive);
FailIfError(r);
r = TheFs.Volume(volInfo, drive);
FailIfError(r);
gMediaSize = volInfo.iSize;
FormatFat(gSessionPath[0]-'A');
TheFs.MkDirAll(gSessionPath);
RThread noisy;
TBuf<20> buf = _L("Noisy");
r = noisy.Create(buf, noise, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
FailIfError(r);
noisy.Resume();
CSelectionBox* TheSelector=CSelectionBox::NewL(test.Console());
if(gMode == 0)
{ // Manual
gSessionPath=_L("?:\\");
TCallBack smallOps(TestSmall, TheSelector);
TCallBack largeOps(TestLarge, TheSelector);
TCallBack simulOps(TestStreaming, TheSelector);
TCallBack tAll(TestAll, TheSelector);
TheSelector->AddDriveSelectorL(TheFs);
TheSelector->AddLineL(_L("Small random r/w"), smallOps);
TheSelector->AddLineL(_L("Large conseq r/w"), largeOps);
TheSelector->AddLineL(_L("Streaming"), simulOps);
TheSelector->AddLineL(_L("Execute all options"), tAll);
TheSelector->Run();
}
else
{ // Automatic
TestAll(TheSelector);
}
DeleteAll(gSessionPath);
client.Close();
delete TheSelector;
delete gBuf;
delete gBufSec;
noisy.Kill(KErrNone);
noisy.Close();
}