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) 1998-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\server\t_dspace.cpp
//
//
#include <f32file.h>
#include <e32test.h>
#include "t_server.h"
#include "t_chlffs.h"
/* This tests disk space notification. Using RFs::NotifyDiskSpace a client can request
to be notified if the free disk space crosses a specified threshold. This test requires
a card to be present in d: */
GLDEF_D RTest test(_L("T_DSPACE"));
const TInt KMaxBufSize=512;
#if defined(__WINS__)
TInt KFileSize1=2048;
TInt KFileSize2=4096;
TInt KFileSize3=8192;
#else
TInt KFileSize1=512;
TInt KFileSize2=1024;
TInt KFileSize3=4096;
#endif
const TInt KHeapSize=0x2000;
const TInt KStackSize=0x4000;
TInt gMinFileSize;
TBool LffsDrive = EFalse;
TBuf8<KMaxBufSize> TheBuffer;
TInt64 TheDiskSize;
TInt RemovableDrive;
TBuf<4> RemovableDriveBuf=_L("?:\\");
_LIT(KTestFile1, "\\F32-TST\\testfile1");
_LIT(KTestFile2, "\\F32-TST\\testFile2");
_LIT(KTestDir1, "\\F32-TST\\testDir1\\");
_LIT(KTestDir2, "\\F32-TST\\testDir2\\");
_LIT(KFileFiller, "\\F32-TST\\fileFiller");
// functions that may cause change in free disk space
// not all of them of tested since some require knowledge of file system
// to ensure change in free disk space
enum TThreadTask
{
ETaskSetVolume,
ETaskMkDir,
ETaskRmDir,
ETaskDelete, // test
ETaskRename,
ETaskReplace, // test
ETaskFileCreate,
ETaskFileReplace, // test
ETaskFileTemp,
ETaskFileWrite, // test
ETaskFileWrite4KB,
ETaskFileWrite64KB,
ETaskFileSetSize, // test
ETaskFileRename,
ETaskNoChange1,
ETaskNoChange2,
ETaskFileCreateLffs,// test
ETaskSpin
};
LOCAL_C TBool IsWinsCDrive(TInt aDrive)
//
//
//
{
#if defined(__WINS__)
if(aDrive==KDefaultDrive)
return(gSessionPath[0]==(TText)'C');
else
return(aDrive==EDriveC);
#else
return(EFalse);
#endif
}
LOCAL_C TInt64 FreeDiskSpace(TInt aDrive)
//
//
//
{
TVolumeInfo v;
TInt r=TheFs.Volume(v,aDrive);
test(r==KErrNone);
return(v.iFree);
}
LOCAL_C TInt64 DiskSize(TInt aDrive)
//
//
//
{
TVolumeInfo v;
TInt r=TheFs.Volume(v,aDrive);
test(r==KErrNone);
return(v.iSize);
}
// MinimumFileSize() -
// Deduces the minimum space occupied by a file by creating a file of one byte
// in length. This should equal the cluster size on FAT volumes.
//
LOCAL_C TInt MinimumFileSize(TInt aDrive)
{
TInt r = TheFs.Delete(KTestFile1);
test(r==KErrNone || r==KErrNotFound);
TInt64 freeSpace = FreeDiskSpace(aDrive);
RFile file;
r=file.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
r = file.Write(TheBuffer,1);
test(r==KErrNone);
file.Close();
TInt64 newSpace = FreeDiskSpace(aDrive);
r = TheFs.Delete(KTestFile1);
test(r==KErrNone);
TInt64 minFileSize = freeSpace - newSpace;
test (minFileSize >= 0);
minFileSize = Max(minFileSize, 512);
test (minFileSize < KMaxTInt);
TInt minFileSizeLow = I64LOW(minFileSize);
RDebug::Print(_L("minFileSize %u"), minFileSizeLow);
#if defined(__WINS__)
KFileSize1 = minFileSizeLow << 2; // 512 * 2^2 = 512 * 4 = 2048;
KFileSize2 = minFileSizeLow << 3; // 512 * 2^3 = 512 * 8 = 4096;
KFileSize3 = minFileSizeLow << 4; // 512 * 2^4 = 512 * 16 = 8192;
#else
KFileSize1 = minFileSizeLow; // 512;
KFileSize2 = minFileSizeLow << 1; // 512 * 2^1 = 512 * 2 = 1024;
KFileSize3 = minFileSizeLow << 3; // 512 * 2^3 = 512 * 8 = 4096;
#endif
return (TInt) minFileSizeLow;
}
LOCAL_C void Initialise()
//
// do any initialisation before starting tests
//
{
if(TheBuffer.Length()!=KMaxBufSize)
{
TheBuffer.SetLength(KMaxBufSize);
Mem::Fill((void*)TheBuffer.Ptr(),KMaxBufSize,0xab);
}
#if defined(__WINS__)
RemovableDrive=EDriveX;
#else
TDriveList drvList;
if(KErrNone == TheFs.DriveList(drvList))
{
TInt i;
//should be successful, otherwise it means a system w/o any drive!!!
for(i=0;i<KMaxDrives;i++)
{
TDriveInfo driveInfo;
if((drvList[i] != 0)
&& (KErrNone == TheFs.Drive(driveInfo, i))
&& (driveInfo.iType == EMediaHardDisk))
{
RemovableDrive = i;
test.Printf(_L("RemovableDrive = %d\n"),RemovableDrive);
break;
}
}
if(i == KMaxDrives)
{
test.Printf(_L("No Removable media found! Testing discontinued.\n"));
User::Exit(KErrNone);
}
}
else
{
test.Printf(_L("No Drive found! Testing discontinued.\n"));
User::Exit(KErrNone);
}
#endif
test.Printf(_L("inside init++++++++++++++++++++++++++>\n\n\n"));
test.Printf(_L("RemovableDrive = %d\n"),RemovableDrive);
// initialise removable drive descriptor
TChar c;
TInt r=RFs::DriveToChar(RemovableDrive,c);
test(r==KErrNone);
RemovableDriveBuf[0]=(TText)c;
if( !LffsDrive )
{
// and create the default directory
TFileName d=gSessionPath;
d[0]=RemovableDriveBuf[0];
MakeDir(d);
}
// better format the default drive as long as not WINS c drive
TInt drive;
r= RFs::CharToDrive(gSessionPath[0],drive);
test(r==KErrNone);
#if defined(__WINS__)
if(drive!=EDriveC)
Format(drive);
#else
Format(drive);
// test not run on c: drive but does use it
Format(EDriveC);
#endif
TheDiskSize=DiskSize(KDefaultDrive);
// and set the default directory
r=TheFs.MkDirAll(gSessionPath);
test(r==KErrNone || r==KErrAlreadyExists);
r=TheFs.Delete(KFileFiller);
test(r==KErrNone || r==KErrNotFound);
r=TheFs.Delete(KTestFile1);
test(r==KErrNone || r==KErrNotFound);
r=TheFs.Delete(KTestFile2);
test(r==KErrNone || r==KErrNotFound);
r=TheFs.RmDir(KTestDir1);
test(r==KErrNone || r==KErrNotFound);
r=TheFs.RmDir(KTestDir2);
test(r==KErrNone || r==KErrNotFound);
gMinFileSize = MinimumFileSize(drive);
}
LOCAL_C TInt64 FillDisk(RFile& aFile,TInt64 aNewSpace,TInt aDrive)
//
// fill a file until free disk space equals aFreeSpace
//
{
TInt64 space=FreeDiskSpace(aDrive);
test(space>aNewSpace);
while(space>aNewSpace)
{
TInt s=Min(KMaxBufSize, I64INT(space-aNewSpace));
TInt r=aFile.Write(TheBuffer,s);
if( !LffsDrive )
{
test(r==KErrNone);
}
else
{
//
// LFFS is less predictable than a normal drive because of the logging
// and metadata arrangement
//
test( (KErrNone==r) || (KErrDiskFull==r) );
if( KErrDiskFull == r )
{
// shrink the file back down again to give the requested free space
TInt fileSize;
r=aFile.Size( fileSize );
test( KErrNone == r );
test( TInt64(fileSize) > aNewSpace );
fileSize -= I64LOW(aNewSpace);
r=aFile.SetSize( fileSize );
test( KErrNone == r );
space=FreeDiskSpace(aDrive);
while( space < aNewSpace )
{
fileSize -= I64LOW(aNewSpace - space);
test( fileSize > 0 );
r=aFile.SetSize( fileSize );
test( KErrNone == r );
space=FreeDiskSpace(aDrive);
}
break;
}
}
space=FreeDiskSpace(aDrive);
}
return(space);
}
LOCAL_C void WriteToFile(RFile& aFile,TInt aSize)
//
//
//
{
while(aSize>0)
{
TInt s=Min(KMaxBufSize,aSize);
TInt r=aFile.Write(TheBuffer,s);
aSize-=s;
// Flush if write caching enabled to ensure we get disk space notifications
if ((gDriveCacheFlags & EFileCacheWriteOn) && (r == KErrNone))
r = aFile.Flush();
if( !LffsDrive )
{
test(r==KErrNone);
}
else
{
// we can't accurately predict the amount of data we can actually get
// on an LFFS drive, so it's posible we could exceed the available
// space even though we are writing less that the reported free space
test( (KErrNone==r) || (KErrDiskFull==r) );
if( KErrDiskFull == r )
{
break; // just stop
}
}
}
}
LOCAL_C void CleanupForThread(TInt aTask)
//
//
//
{
TInt r;
switch(aTask)
{
case ETaskMkDir:
r=TheFs.RmDir(KTestDir1);
test(r==KErrNone);
break;
case ETaskRmDir: break;
case ETaskDelete: break;
case ETaskReplace:
r=TheFs.Delete(KTestFile2);
test(r==KErrNone);
break;
case ETaskFileReplace:
r=TheFs.Delete(KTestFile1);
test(r==KErrNone);
break;
case ETaskFileWrite:
case ETaskFileWrite4KB:
case ETaskFileWrite64KB:
case ETaskFileSetSize:
case ETaskFileCreateLffs:
case ETaskNoChange1:
case ETaskNoChange2:
r=TheFs.Delete(KTestFile1);
if(r!=KErrNone)
{
test.Printf(_L("r=%d"),r);
test(EFalse);
}
break;
case ETaskSpin:
default:break;
}
}
LOCAL_C void InitialiseForThread(TInt aTask)
//
//
//
{
TInt r;
RFile file,file2;
switch(aTask)
{
case ETaskMkDir: break;
case ETaskRmDir:
r=TheFs.MkDir(KTestDir1);
test(r==KErrNone);
break;
case ETaskDelete:
r=file.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
if( !LffsDrive )
{
r=file.SetSize(KFileSize1);
test(r==KErrNone);
}
else
{
// LFFS supports sparse files, so we have to write real data
// into the file to ensure that it uses up disk space
WriteToFile( file, KFileSize1 );
}
file.Close();
break;
case ETaskReplace:
r=file.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
if( !LffsDrive )
{
r=file.SetSize(KFileSize1);
test(r==KErrNone);
}
else
{
WriteToFile( file, KFileSize2 );
}
file.Close();
r=file2.Create(TheFs,KTestFile2,EFileShareAny|EFileWrite);
test(r==KErrNone);
if( !LffsDrive )
{
r=file2.SetSize(KFileSize3);
test(r==KErrNone);
}
else
{
WriteToFile( file2, gMinFileSize << 4); // 512 * 16 = 8K
}
file2.Close();
break;
case ETaskFileReplace:
r=file.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
if( !LffsDrive )
{
r=file.SetSize(KFileSize3*2);
}
else
{
WriteToFile( file, KFileSize3 );
}
test(r==KErrNone);
file.Close();
break;
case ETaskFileWrite:
case ETaskFileWrite4KB:
case ETaskFileWrite64KB:
case ETaskFileSetSize:
r=file.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
file.Close();
break;
case ETaskNoChange1:
r=file.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
if( !LffsDrive )
{
r=file.SetSize(KFileSize1);
test(r==KErrNone);
}
else
{
WriteToFile( file, KFileSize1 );
}
file.Close();
break;
case ETaskNoChange2:
r=file.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
file.Close();
break;
case ETaskFileCreateLffs:
r = TheFs.Delete(KTestFile1);
break;
case ETaskSpin:
default:break;
}
}
LOCAL_C TInt ThreadFunction(TAny* aThreadTask)
//
//
//
{
RTest test(_L("T_DSPACE_ThreadFunction"));
RFs fs;
TInt r=fs.Connect();
test(r==KErrNone);
r=fs.SetSessionPath(gSessionPath);
test(r==KErrNone);
TThreadTask task=*(TThreadTask*)&aThreadTask;
RFile file;
switch(task)
{
case ETaskMkDir:
r=fs.MkDir(KTestDir1);
test(r==KErrNone);
break;
case ETaskRmDir:
r=fs.RmDir(KTestDir1);
test(r==KErrNone);
break;
case ETaskDelete:
r=fs.Delete(KTestFile1);
test(r==KErrNone);
break;
case ETaskReplace:
r=fs.Replace(KTestFile1,KTestFile2);
test(r==KErrNone);
break;
case ETaskFileReplace:
r=file.Replace(fs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
file.Close();
break;
case ETaskFileWrite:
r=file.Open(fs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
#if defined(__WINS__)
WriteToFile( file, gMinFileSize << 4); // 512 * 16 = 8K
#else
WriteToFile( file, gMinFileSize << 1); // 512 * 2 = 1K
#endif
file.Close();
break;
case ETaskFileWrite4KB:
r=file.Open(fs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
WriteToFile(file,gMinFileSize << 3); // 512 * 2^3 = 512 * 8 = 4K
file.Close();
break;
case ETaskFileWrite64KB:
r=file.Open(fs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
WriteToFile(file,gMinFileSize<<7); // 512 * 2^7 = 512 * 128 = 64K
file.Close();
break;
case ETaskFileSetSize:
r=file.Open(fs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
r=file.SetSize(KFileSize3);
file.Close();
break;
case ETaskFileCreateLffs:
r=file.Create(fs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
file.Close();
break;
case ETaskNoChange1:
{
r=file.Open(fs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
TTime time;
time.HomeTime();
r=file.SetModified(time);
test(r==KErrNone);
file.Close();
break;
}
case ETaskNoChange2:
{
TEntry e;
r=fs.Entry(KTestFile1,e);
test(r==KErrNone);
break;
}
case ETaskSpin:
for(;;) {};
default:break;
}
fs.Close();
return(KErrNone);
}
void TestCancellation()
//
// test error disk space notification requests can be cancelled
//
{
test.Next(_L("test disk space cancellation"));
const TInt ThresholdSize=500;
// test a cancellation
// Up the priority of this thread so that we can cancel the request before the drive thread
// runs, to test whether cancelling still works.
RThread().SetPriority(EPriorityRealTime);
TRequestStatus stat1;
TheFs.NotifyDiskSpace(ThresholdSize,KDefaultDrive,stat1);
test(stat1==KRequestPending);
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat1==KErrCancel);
RThread().SetPriority(EPriorityNormal);
// test no affect if already cancelled
stat1=KErrNone;
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat1==KErrNone);
// set up two requests, cancel 1
TRequestStatus stat2;
TheFs.NotifyDiskSpace(ThresholdSize,KDefaultDrive,stat1);
TheFs.NotifyDiskSpace(ThresholdSize,KDefaultDrive,stat2);
test(stat1==KRequestPending && stat2==KRequestPending);
TheFs.NotifyDiskSpaceCancel(stat2);
test(stat1==KRequestPending && stat2==KErrCancel);
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat1==KErrCancel);
if( !LffsDrive)
{
// now repeat with c: and removable drive
TheFs.NotifyDiskSpace(ThresholdSize,EDriveC,stat1);
TheFs.NotifyDiskSpace(ThresholdSize,RemovableDrive,stat2);
test(stat1==KRequestPending && stat2==KRequestPending);
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat2==KRequestPending && stat1==KErrCancel);
TheFs.NotifyDiskSpaceCancel(stat2);
test(stat2==KErrCancel);
}
}
void TestErrorConditions()
//
// test disk space notification requests return correct error value
//
{
test.Next(_L("test error conditions"));
// attempt to set up disk space notification with a threshold of zero
TRequestStatus status;
TheFs.NotifyDiskSpace(0,KDefaultDrive,status);
test(status==KErrArgument);
// test on an empty drive
TheFs.NotifyDiskSpace(100,EDriveO,status);
test(status==KErrNotReady);
// test on a drive out of rance
TheFs.NotifyDiskSpace(100,27,status);
test(status==KErrBadName);
// new setup with threshold of one
TheFs.NotifyDiskSpace(1,KDefaultDrive,status);
test(status==KRequestPending);
TheFs.NotifyDiskSpaceCancel(status);
test(status==KErrCancel);
// and with a threshold > disk size
TheFs.NotifyDiskSpace(TheDiskSize+10,KDefaultDrive,status);
test(status==KErrArgument);
// now with a size of max size -1
TheFs.NotifyDiskSpace(TheDiskSize-1,KDefaultDrive,status);
test(status==KRequestPending);
TheFs.NotifyDiskSpaceCancel(status);
test(status==KErrCancel);
// set up mutiple requests and cancel one
TRequestStatus status2,status3;
TheFs.NotifyDiskSpace(TheDiskSize-10,KDefaultDrive,status);
TheFs.NotifyDiskSpace(TheDiskSize-10,KDefaultDrive,status2);
TheFs.NotifyDiskSpace(TheDiskSize-10,KDefaultDrive,status3);
test(status==KRequestPending&&status2==KRequestPending&&status3==KRequestPending);
TheFs.NotifyDiskSpaceCancel(status3);
test(status==KRequestPending&&status2==KRequestPending&&status3==KErrCancel);
// cancel the remaining ones
TheFs.NotifyDiskSpaceCancel();
test(status==KErrCancel&&status2==KErrCancel&&status3==KErrCancel);
}
TInt GenerateMediaChange()
{
RLocalDrive d;
TBool flag=EFalse;
//Find the local drive number corresponding to removabledrive
TMediaSerialNumber serialNum;
TInt r = TheFs.GetMediaSerialNumber(serialNum, RemovableDrive);
if(r!= KErrNone)
return r;
TInt len = serialNum.Length();
test.Printf(_L("Serial number (len %d) :"), len);
TInt localDriveNum = -1;
for (TInt n=0; n<KMaxLocalDrives; n++)
{
r = d.Connect(n, flag);
if(r != KErrNone)
{
test.Printf(_L("drive %d: TBusLocalDrive::Connect() failed %d\n"), n, r);
continue;
}
TLocalDriveCapsV5Buf capsBuf;
TLocalDriveCapsV5& caps = capsBuf();
r = d.Caps(capsBuf);
if(r != KErrNone)
{
test.Printf(_L("drive %d: TBusLocalDrive::Caps() failed %d\n"), n, r);
continue;
}
TPtrC8 localSerialNum(caps.iSerialNum, caps.iSerialNumLength);
if (serialNum.Compare(localSerialNum) == 0)
{
localDriveNum = n;
d.Close();
break;
}
d.Close();
}
r =d.Connect(localDriveNum,flag);
if (r!=KErrNone)
return r;
d.ForceMediaChange();
d.Close();
return KErrNone;
}
void TestDiskNotify()
//
// test functions that can result in disk change notification
// format,scandrive, media change
//
{
// make default directory
_LIT(defaultDir,"C:\\F32-TST\\");
TInt r=TheFs.MkDirAll(defaultDir);
test(r==KErrNone||r==KErrAlreadyExists);
// create the filler file
RFile file;
TFileName fileName=_L("C:");
fileName+=KFileFiller;
r=file.Create(TheFs,fileName,EFileShareAny|EFileWrite);
test(r==KErrNone);
TInt64 free=FreeDiskSpace(EDriveC);
// use up 16KB
FillDisk(file,free-16384,EDriveC);
// test formatting notifies clients on only specific drive
test.Next(_L("test formatting"));
TRequestStatus stat1, stat2;
TInt64 freeC=FreeDiskSpace(EDriveC);
TInt64 freeD=FreeDiskSpace(RemovableDrive);
TheFs.NotifyDiskSpace(freeC+1024,EDriveC,stat1);
TheFs.NotifyDiskSpace(freeD-1024,RemovableDrive,stat2);
test(stat1==KRequestPending && stat2==KRequestPending);
RFormat f;
TInt count;
r=f.Open(TheFs,RemovableDriveBuf,EQuickFormat,count);
test(r==KErrNone);
while(count)
{
r=f.Next(count);
test(r==KErrNone);
}
f.Close();
User::After(1000000);
User::WaitForRequest(stat2);
test(stat1==KRequestPending && stat2==KErrNone);
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat1==KErrCancel);
// and create the test directory for the removable drive
TFileName fName=_L("");
fName+=RemovableDriveBuf;
fName+=_L("F32-TST\\");
r=TheFs.MkDirAll(fName);
test(r==KErrNone);
// test that a media change notifies clients on all drives
test.Next(_L("media change"));
freeC=FreeDiskSpace(EDriveC);
freeD=FreeDiskSpace(RemovableDrive);
test.Printf(_L("free space on drive %d = 0x%x\n"),EDriveC,freeC);
test.Printf(_L("free space on drive %d = 0x%x\n"),RemovableDrive,freeD);
TheFs.NotifyDiskSpace(freeC+1024,EDriveC,stat1);
TheFs.NotifyDiskSpace(freeD-1024,RemovableDrive,stat2);
test(stat1==KRequestPending && stat2==KRequestPending);
// UserSvr::ForceRemountMedia(ERemovableMedia0);
r = GenerateMediaChange();
if(r == KErrNone)
{
User::After(1000000);
User::WaitForRequest(stat2);
test(stat1==KRequestPending && stat2==KErrNone);
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat1==KErrCancel);
}
else
{
test.Printf(_L("media change not supported, skipping this step\n"));
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat1 == KErrCancel);
TheFs.NotifyDiskSpaceCancel(stat2);
test(stat2 == KErrCancel);
}
// test that scandrive notifies clients on only specific drives
test.Next(_L("scandrive"));
// first test that scandrive does not find any problems on the removable media
r=TheFs.ScanDrive(RemovableDriveBuf);
test(r==KErrNone);
// now set up disk space notification
freeC=FreeDiskSpace(EDriveC);
freeD=FreeDiskSpace(RemovableDrive);
test.Printf(_L("free space on drive %d = 0x%x\n"),EDriveC,freeC);
test.Printf(_L("free space on drive %d = 0x%x\n"),RemovableDrive,freeD);
TheFs.NotifyDiskSpace(freeC+8192,EDriveC,stat1);
TheFs.NotifyDiskSpace(freeD-8192,RemovableDrive,stat2);
test(stat1==KRequestPending && stat2==KRequestPending);
r=TheFs.ScanDrive(RemovableDriveBuf);
test(r==KErrNone);
User::After(1000000);
User::WaitForRequest(stat2);
test(stat1==KRequestPending && stat2==KErrNone);
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat1==KErrCancel);
file.Close();
r=TheFs.Delete(fileName);
test(r==KErrNone);
if(gSessionPath[0]!=(TText)'C')
{
r=TheFs.RmDir(defaultDir);
test(r==KErrNone||r==KErrInUse);
}
}
void TestFunctions()
//
// test some of the functions that may result in a change in free disk space
// not testing all functions that may result in free disk space change since
// change is dependent on the file system
//
{
test.Next(_L("test disk space functions"));
// create the filler file
RFile file;
TInt r=file.Create(TheFs,KFileFiller,EFileShareAny|EFileWrite|EFileWriteDirectIO);
test(r==KErrNone);
TInt64 newSpace = FreeDiskSpace(KDefaultDrive)-8192;
FillDisk(file,newSpace,KDefaultDrive);
// check file write
test.Next(_L("check RFile:Write"));
TThreadTask task=ETaskFileWrite;
InitialiseForThread(task);
TInt64 free=FreeDiskSpace(KDefaultDrive);
TRequestStatus stat1;
TInt64 threshold=free-200;
TheFs.NotifyDiskSpace(threshold,KDefaultDrive,stat1);
test(stat1==KRequestPending);
RThread thread;
r=thread.Create(_L("thread1"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Resume();
User::WaitForRequest(stat1);
test(stat1==KErrNone);
free=FreeDiskSpace(KDefaultDrive);
test(free<threshold);
TRequestStatus deathStat;
thread.Logon( deathStat );
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
// check file set size
// setting file size on LFFS only uses a small amount of disk space for metadata
// so we skip this test for an LFFS drive
if( !LffsDrive )
{
test.Next(_L("check RFile:SetSize"));
task=ETaskFileSetSize;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
threshold=free-100;
TheFs.NotifyDiskSpace(threshold,KDefaultDrive,stat1);
test(stat1==KRequestPending);
r=thread.Create(_L("thread2"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
TRequestStatus deathStat;
thread.Logon( deathStat );
thread.Resume();
User::WaitForRequest(stat1);
test(stat1==KErrNone);
free=FreeDiskSpace(KDefaultDrive);
test(free<threshold);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
}
// check disk space notification does not occur when threshold not crossed
TInt64 newFree;
test.Next(_L("check RFile:SetSize with wrong threshold"));
User::After(1000000); //put in due to thread latency
task=ETaskFileSetSize;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
threshold=free+100;
TheFs.NotifyDiskSpace(threshold,KDefaultDrive,stat1);
test(stat1==KRequestPending);
r=thread.Create(_L("thread3"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::After(1000000);
test(stat1==KRequestPending);
newFree=FreeDiskSpace(KDefaultDrive);
/*
test.Printf(_L("threshold = %d and %d"),threshold.High(), threshold.Low());
test.Printf(_L("free = %d and %d"),free.High(), free.Low());
test.Printf(_L("newFree = %d and %d"),newFree.High(), newFree.Low());
*/
if(!LffsDrive)
test(free<threshold && newFree<free);
else
test(free<threshold); //changing file size on lffs does not do anything
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
TheFs.NotifyDiskSpaceCancel(stat1);
test(stat1==KErrCancel);
// check for file delete
test.Next(_L("check RFs::Delete"));
task=ETaskDelete;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
threshold=free+300;
TheFs.NotifyDiskSpace(threshold,KDefaultDrive,stat1);
test(stat1==KRequestPending);
r=thread.Create(_L("thread4"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::WaitForRequest(stat1);
test(stat1==KErrNone);
free=FreeDiskSpace(KDefaultDrive);
test(free>threshold);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
// check for replace with threshold too high
test.Next(_L("check RFs::Replace with threshold too high"));
if( LffsDrive )
{
test.Printf( _L("Skipped.... test isn't consistent on LFFS drive\n") );
}
else
{
task=ETaskReplace;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
#if defined(__WINS__)
threshold=free + gMinFileSize * 16 + 2048; // 512 * 16 + 2K = 10K
#else
if(LffsDrive )
threshold=free + (gMinFileSize << 4) + 2048; // 512 * 16 + 2K = 10K
else
threshold=free + gMinFileSize * 9 + 392; // 512 * 9 + 392 = 5000;
#endif
TheFs.NotifyDiskSpace(threshold,KDefaultDrive,stat1);
test(stat1==KRequestPending);
r=thread.Create(_L("thread5"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::After(1000000);
test(stat1==KRequestPending);
newFree=FreeDiskSpace(KDefaultDrive);
test(newFree<threshold && free<newFree);
TheFs.NotifyDiskSpaceCancel();
test(stat1==KErrCancel);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
// check for replace
test.Next(_L("check RFs:Replace"));
task=ETaskReplace;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
threshold=free+200;
TheFs.NotifyDiskSpace(threshold,KDefaultDrive,stat1);
test(stat1==KRequestPending);
r=thread.Create(_L("thread6"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::WaitForRequest(stat1);
//User::After(1000000);
test(stat1==KErrNone);
User::WaitForRequest( deathStat );
test(deathStat==KErrNone);
thread.Close();
CleanupForThread(task);
free=FreeDiskSpace(KDefaultDrive);
test(free>threshold);
}
// check that CSessionFS::iTheDrive is set in subsession calls
test.Next(_L("Check iTheDrive and subsessions"));
if( LffsDrive )
{
test.Printf( _L("Skipped.... test not done on LFFS drive\n") );
}
else
{
RFile f2;
#if defined(__WINS__)
_LIT(someFile,"X:\\abcdef");
#else
TBuf<10> someFile=_L("?:\\abcdef");
TChar c;
TInt r=RFs::DriveToChar(RemovableDrive,c);
test(r==KErrNone);
someFile[0]=(TText)c;
#endif
_LIT(someDir,"C:\\1234\\");
r=f2.Create(TheFs,someFile,EFileShareAny|EFileWrite);
test(r==KErrNone);
r=TheFs.MkDir(someDir);
test(r==KErrNone);
TRequestStatus stat2;
TInt64 freeC=FreeDiskSpace(EDriveC);
TInt64 freeD=FreeDiskSpace(RemovableDrive);
TheFs.NotifyDiskSpace(freeC-4097,EDriveC,stat1);
TheFs.NotifyDiskSpace(freeD-4097,RemovableDrive,stat2);
test(stat1==KRequestPending && stat2==KRequestPending);
// before fix this would result in iTheDrive not being updated in next subsession call
// therefore this could would not result in a disk space notification
r=f2.SetSize(8192);
test(r==KErrNone);
User::After(1000000);
User::WaitForRequest(stat2);
if (stat2!=KErrNone)
test.Printf(_L("stat2=%d\n"),stat2.Int());
test(stat2==KErrNone);
if (stat1!=KRequestPending)
test.Printf(_L("stat1=%d\n"),stat1.Int());
test(stat1==KRequestPending);
f2.Close();
TheFs.NotifyDiskSpaceCancel();
test(stat1==KErrCancel);
r=TheFs.Delete(someFile);
test(r==KErrNone);
r=TheFs.RmDir(someDir);
test(r==KErrNone);
}
file.Close();
r=TheFs.Delete(KFileFiller);
test(r==KErrNone);
}
void TestLffsFunctions()
//
// LFFS-specific tests for some functions which may cause a disk
// space change
//
//
{
test.Next(_L("test LFFS disk space functions"));
// create the filler file
RFile file;
TInt r=file.Create(TheFs,KFileFiller,EFileShareAny|EFileWrite|EFileWriteDirectIO);
test(r==KErrNone);
TInt64 newSpace = FreeDiskSpace(KDefaultDrive)-8192;
FillDisk(file,newSpace,KDefaultDrive);
// check file create
// Creating a file will always allocate space for the inode
test.Next(_L("check RFile:Create"));
TThreadTask task=ETaskFileCreateLffs;
InitialiseForThread(task);
TInt64 free=FreeDiskSpace(KDefaultDrive);
TInt64 threshold1=free-64;
TInt64 threshold2=free-KFileSize3;
TRequestStatus stat1, stat2;
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
TheFs.NotifyDiskSpace(threshold2,KDefaultDrive,stat2);
test(stat1==KRequestPending && stat2==KRequestPending);
RThread thread;
r=thread.Create(_L("thread7"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
TRequestStatus deathStat;
thread.Logon( deathStat );
thread.Resume();
User::WaitForRequest(stat1);
test(stat1==KErrNone);
free=FreeDiskSpace(KDefaultDrive);
test(free<threshold1);
test(stat2==KRequestPending);
test(free>threshold2);
TheFs.NotifyDiskSpaceCancel(stat2);
User::WaitForRequest(stat2);
test(stat2==KErrCancel);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
TInt64 threshold3;
TRequestStatus stat3;
RFile file2;
// don't test for wins urel since cant use RFs::ControlIo
#if defined(_DEBUG)
// check background thread notification
test.Next(_L("check Background thread notification"));
task=ETaskSpin; // create thread to block background thread
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
threshold1=free-64; // this should occur when we create test file
threshold2=free+9750; // some impossible value
threshold3=free+10000; // some other impossible value that will never happen
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
TheFs.NotifyDiskSpace(threshold2,KDefaultDrive,stat2);
TheFs.NotifyDiskSpace(threshold3,KDefaultDrive,stat3);
test(stat1==KRequestPending && stat2==KRequestPending && stat3==KRequestPending);
r=thread.Create(_L("thread8"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.SetPriority( EPriorityLess );
thread.Resume(); // start spinning, blocks background thread
// request background thread to notify a daft value
TPckgBuf<TInt64> cBuf;
cBuf() = threshold2;
// Hard code the value of ECioBackgroundNotifyDiskSize.
// Although the value is enumerated in f32\slffs\lffs_controlio.h this header file is being
// removed from the release codeline but retained in the base team development codeline.
#define ECioBackgroundNotifyDiskSize 10016
r = TheFs.ControlIo(GetDriveLFFS(), ECioBackgroundNotifyDiskSize, cBuf);
test( KErrNone==r );
// create a file to force some roll-forward
r=file2.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
User::WaitForRequest(stat1);
test(stat1==KErrNone);
test(stat2==KRequestPending);
test(stat3==KRequestPending);
// kill the spinner thread to allow the background thread to execute
thread.Kill(KErrNone);
User::WaitForRequest( deathStat );
thread.Close();
// wait for the notifier
User::WaitForRequest(stat2);
test( stat2==KErrNone );
test( stat3==KRequestPending);
TheFs.NotifyDiskSpaceCancel(stat3);
User::WaitForRequest(stat3);
test(stat3==KErrCancel);
CleanupForThread(task);
file2.Close();
TheFs.Delete( KTestFile1 );
#endif
// check background thread notification again, this time we won't request
// a special value - check that it notifies normally
test.Next(_L("check Background thread notification again"));
task=ETaskSpin; // create thread to block background thread
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
threshold1=free-64; // this should occur when we create test file
threshold2=free+9750; // some impossible value
threshold3=free+10000; // some other impossible value that will never happen
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
TheFs.NotifyDiskSpace(threshold2,KDefaultDrive,stat2);
TheFs.NotifyDiskSpace(threshold3,KDefaultDrive,stat3);
test(stat1==KRequestPending && stat2==KRequestPending && stat3==KRequestPending);
r=thread.Create(_L("thread9"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.SetPriority( EPriorityLess );
thread.Resume(); // start spinning, blocks background thread
// create a file to force some roll-forward
r=file2.Create(TheFs,KTestFile1,EFileShareAny|EFileWrite);
test(r==KErrNone);
User::WaitForRequest(stat1);
test(stat1==KErrNone);
test(stat2==KRequestPending);
test(stat3==KRequestPending);
// kill the spinner thread to allow the background thread to execute
thread.Kill(KErrNone);
User::WaitForRequest( deathStat );
thread.Close();
// wait for the notifier
test( stat2==KRequestPending );
test( stat3==KRequestPending);
TheFs.NotifyDiskSpaceCancel(stat2);
User::WaitForRequest(stat2);
test(stat2==KErrCancel);
TheFs.NotifyDiskSpaceCancel(stat3);
User::WaitForRequest(stat3);
test(stat3==KErrCancel);
CleanupForThread(task);
file2.Close();
TheFs.Delete( KTestFile1 );
file.Close();
r=TheFs.Delete(KFileFiller);
test(r==KErrNone);
}
void TestMultiple()
//
// test muliple requests and multiple sessions
//
{
// create the filler file
RFile file;
TInt r=file.Create(TheFs,KFileFiller,EFileShareAny|EFileWrite|EFileWriteDirectIO);
test(r==KErrNone);
TInt64 free=FreeDiskSpace(KDefaultDrive);
TInt64 freeSpaceLeft = gMinFileSize << 4; // 512 * 2^4 = 512 * 16 = 8K
FillDisk(file,free-freeSpaceLeft,KDefaultDrive);
TInt size;
r=file.Size(size);
test(r==KErrNone);
test(size>1024);
test.Printf(_L("filler file size=0x%x\n"),size);
// test multiple requests
test.Next(_L("test multiple requests"));
TThreadTask task = ETaskFileWrite4KB;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
TInt64 threshold1=free-gMinFileSize; // 512;
TInt64 threshold2=free - (gMinFileSize << 2); // 512 * 4 = 2048;
#if defined(__WINS__)
TInt64 threshold3=free-70000; //NTFS over-allocates then reduces when file closed
#else
TInt64 threshold3=free - (gMinFileSize << 5); // 512 * 2^5 = 512 * 32 = 16K
#endif
TRequestStatus stat1,stat2,stat3;
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
TheFs.NotifyDiskSpace(threshold2,KDefaultDrive,stat2);
TheFs.NotifyDiskSpace(threshold3,KDefaultDrive,stat3);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
RThread thread;
r=thread.Create(_L("thread1"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
TRequestStatus deathStat;
thread.Logon( deathStat );
thread.Resume();
User::After(1000000);
User::WaitForRequest(stat1);
User::WaitForRequest(stat2);
test(stat1==KErrNone && stat2==KErrNone);
test(stat3==KRequestPending);
free=FreeDiskSpace(KDefaultDrive);
test(free<threshold1 && free<threshold2 && free>threshold3);
TheFs.NotifyDiskSpaceCancel(stat3);
test(stat3==KErrCancel);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
// test multiple requests again
test.Next(_L("test multiple requests again"));
if( LffsDrive )
{
// SetSize doesn't use disk space on LFFS
test.Printf( _L("test skipped on LFFS drive\n") );
}
else
{
task=ETaskFileSetSize;
InitialiseForThread(task); // this also does initialisation for task2
free=FreeDiskSpace(KDefaultDrive);
threshold1 = free + (gMinFileSize << 1); // 512 * 2 = 1024
threshold2 = free + (gMinFileSize * 12); // 512 * 12 = 6144
threshold3 = free - (gMinFileSize << 1); // 512 * 2 = 1024;
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
TheFs.NotifyDiskSpace(threshold2,KDefaultDrive,stat2);
TheFs.NotifyDiskSpace(threshold3,KDefaultDrive,stat3);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
r=thread.Create(_L("thread2"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::After(10000);
User::WaitForRequest(stat3);
test(stat3==KErrNone && stat1==KRequestPending && stat2==KRequestPending);
free=FreeDiskSpace(KDefaultDrive);
test(free<threshold1);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
if(!IsWinsCDrive(KDefaultDrive))
{
free=FreeDiskSpace(KDefaultDrive);
test(stat1==KRequestPending && stat2==KRequestPending);
file.SetSize(size - (gMinFileSize << 2)); // 512 * 4 = 2048
free=FreeDiskSpace(KDefaultDrive);
User::After(1000000);
User::WaitForRequest(stat1);
//User::WaitForRequest(stat2);
test(stat1==KErrNone && stat2==KRequestPending);
free=FreeDiskSpace(KDefaultDrive);
test(free>threshold1 && free<threshold2);
TheFs.NotifyDiskSpaceCancel();
test(stat2==KErrCancel);
}
else
{
TheFs.NotifyDiskSpaceCancel();
test(stat1==KErrCancel&&stat2==KErrCancel&&stat3==KErrNone);
}
}
// test multiple sessions all notified on disk space change
test.Next(_L("test multiple sessions on same drive"));
RFs ses2,ses3;
r=ses2.Connect();
test(r==KErrNone);
r=ses3.Connect();
test(r==KErrNone);
r=ses2.SetSessionPath(gSessionPath);
test(r==KErrNone);
r=ses3.SetSessionPath(gSessionPath);
test(r==KErrNone);
task=ETaskFileReplace;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
test.Printf(_L("free space on default drive = 0x%x\n"),free);
threshold1=free+gMinFileSize; // 512
threshold2=free+(gMinFileSize << 1); // 1024;
threshold3=free+(gMinFileSize << 2); // 2048;
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
ses2.NotifyDiskSpace(threshold2,KDefaultDrive,stat2);
ses3.NotifyDiskSpace(threshold3,KDefaultDrive,stat3);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
r=thread.Create(_L("thread3"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::After(1000000);
User::WaitForRequest(stat1);
User::WaitForRequest(stat2);
User::WaitForRequest(stat3);
test(stat1==KErrNone && stat2==KErrNone && stat3==KErrNone);
free=FreeDiskSpace(KDefaultDrive);
test(free>threshold1 && free>threshold2 && free>threshold3);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
// test NotifyDiskSpaceCancel()
test.Next(_L("test RFs:NotifyDiskSpaceCancel"));
free=FreeDiskSpace(KDefaultDrive);
TheFs.NotifyDiskSpace(free-100,KDefaultDrive,stat1);
ses2.NotifyDiskSpace(free-100,KDefaultDrive,stat2);
ses3.NotifyDiskSpace(free-100,KDefaultDrive,stat3);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
TheFs.NotifyDiskSpaceCancel();
test(stat1==KErrCancel&&stat2==KRequestPending&&stat3==KRequestPending);
ses2.NotifyDiskSpaceCancel(stat2);
test(stat2==KErrCancel&&stat3==KRequestPending);
ses3.NotifyDiskSpaceCancel();
test(stat3==KErrCancel);
if( !LffsDrive )
{
TInt sessionDrive;
r=RFs::CharToDrive(gSessionPath[0],sessionDrive);
test(r==KErrNone);
if(sessionDrive!=RemovableDrive)
{
// first create a file on the removable drive
RFile file2;
TFileName file2name=RemovableDriveBuf;
file2name+=_L("F32-TST\\testfile1");
TheFs.Delete(file2name);
r=file2.Create(TheFs,file2name,EFileShareAny|EFileWrite);
test(r==KErrNone);
r=file2.SetSize(KFileSize3);
test(r==KErrNone);
// test multiple sessions not notified on disk space change on wrong drive
test.Next(_L("test multiple sessions on different drives"));
task=ETaskFileReplace;
InitialiseForThread(task);
TInt64 freeDef=FreeDiskSpace(KDefaultDrive);
TInt64 freeRem=FreeDiskSpace(RemovableDrive);
threshold1=freeDef + (gMinFileSize << 1); // 1024;
threshold2=freeRem + (gMinFileSize << 1); // 1024;
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
ses2.NotifyDiskSpace(threshold2,RemovableDrive,stat2);
test(stat1==KRequestPending&&stat2==KRequestPending);
r=thread.Create(_L("thread4"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::After(1000000);
User::WaitForRequest(stat1);
test(stat1==KErrNone && stat2==KRequestPending);
free=FreeDiskSpace(KDefaultDrive);
test(free>threshold1);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
TheFs.NotifyDiskSpaceCancel(stat2);
test(stat2==KRequestPending);
ses2.NotifyDiskSpaceCancel(stat2);
test(stat2==KErrCancel);
file2.Close();
r=TheFs.Delete(file2name);
test(r==KErrNone);
}
}
ses2.Close();
ses3.Close();
file.Close();
r=TheFs.Delete(KFileFiller);
test(r==KErrNone);
}
void TestLffsMultiple()
//
// test muliple requests and multiple sessions speicifcally for LFFS drive
//
{
// create the filler file
RFile file;
TInt r=file.Create(TheFs,KFileFiller,EFileShareAny|EFileWrite|EFileWriteDirectIO);
test(r==KErrNone);
TInt64 free=FreeDiskSpace(KDefaultDrive);
FillDisk(file,free-8192,KDefaultDrive);
TInt size;
r=file.Size(size);
test(r==KErrNone);
test.Printf(_L("filler file size=0x%x\n"),size);
// test multiple requests again
test.Next(_L("test multiple requests on LFFS") );
TThreadTask task=ETaskFileCreateLffs;
InitialiseForThread(task); // this also does initialisation for task2
free=FreeDiskSpace(KDefaultDrive);
TInt64 threshold1=free+8192;
TInt64 threshold2=free+700; //increased threshold as LFFS, unpredicatably, can release drive space
TInt64 threshold3=free-64;
TRequestStatus stat1, stat2, stat3;
//test.Printf(_L("set up notifiers"));
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
TheFs.NotifyDiskSpace(threshold2,KDefaultDrive,stat2);
TheFs.NotifyDiskSpace(threshold3,KDefaultDrive,stat3);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
RThread thread;
r=thread.Create(_L("thread10"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
TRequestStatus deathStat;
thread.Logon( deathStat );
// test.Printf(_L("Resuming other thread"));
thread.Resume();
User::After(10000);
User::WaitForRequest(stat3);
test(stat3==KErrNone && stat1==KRequestPending && stat2==KRequestPending);
free=FreeDiskSpace(KDefaultDrive);
test(free<threshold1);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
free=FreeDiskSpace(KDefaultDrive);
// test.Printf(_L("free =%d and %d"),free.Low(), free.High());
// test.Printf(_L("stat1=%d, stat2=%d"),stat1,stat2);
test(stat1==KRequestPending && stat2==KRequestPending);
file.SetSize(6144);
User::After(1000000);
User::WaitForRequest(stat2);
test(stat1==KRequestPending && stat2==KErrNone);
free=FreeDiskSpace(KDefaultDrive);
test(free<threshold1 && free>threshold2);
TheFs.NotifyDiskSpaceCancel();
User::WaitForRequest( stat1 );
test(stat1==KErrCancel);
TInt sessionDrive;
r=RFs::CharToDrive(gSessionPath[0],sessionDrive);
test(r==KErrNone);
if(sessionDrive!=EDriveC)
{
// test multiple sessions not notified on disk space change on wrong drive
test.Next(_L("test multiple sessions on different drives"));
RFs ses2,ses3;
r=ses2.Connect();
test(r==KErrNone);
r=ses3.Connect();
test(r==KErrNone);
r=ses2.SetSessionPath(gSessionPath);
test(r==KErrNone);
r=ses3.SetSessionPath(gSessionPath);
test(r==KErrNone);
// first create a file on the C:\ drive
RFile file2;
TFileName file2name=_L("C:\\");
file2name+=_L("F32-TST\\");
r=TheFs.MkDir(file2name);
test( KErrNone==r || KErrAlreadyExists==r );
file2name+=_L("testfile1");
TheFs.Delete(file2name);
r=file2.Create(TheFs,file2name,EFileShareAny|EFileWrite);
test(r==KErrNone);
WriteToFile( file2, KFileSize3 );
task=ETaskFileReplace;
InitialiseForThread(task);
TInt64 freeLffs=FreeDiskSpace(KDefaultDrive);
TInt64 freeD=FreeDiskSpace(EDriveC);
threshold1=freeLffs+1024;
threshold2=freeD+1024;
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
ses2.NotifyDiskSpace(threshold2,EDriveC,stat2);
test(stat1==KRequestPending&&stat2==KRequestPending);
r=thread.Create(_L("thread11"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::After(1000000);
User::WaitForRequest(stat1);
test(stat1==KErrNone && stat2==KRequestPending);
free=FreeDiskSpace(KDefaultDrive);
test(free>threshold1);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
TheFs.NotifyDiskSpaceCancel(stat2);
test(stat2==KRequestPending);
ses2.NotifyDiskSpaceCancel(stat2);
User::WaitForRequest( stat2 );
test(stat2==KErrCancel);
file2.Close();
r=TheFs.Delete(file2name);
test(r==KErrNone);
ses2.Close();
ses3.Close();
}
file.Close();
r=TheFs.Delete(KFileFiller);
test(r==KErrNone);
}
void TestChangeNotification()
//
// test that disk space notification works with (extended) change notification
//
{
// create a filler file
RFile file;
TInt r=file.Create(TheFs,KFileFiller,EFileShareAny|EFileWrite|EFileWriteDirectIO);
test(r==KErrNone);
TInt64 free=FreeDiskSpace(KDefaultDrive);
// use 8KB in filler file
FillDisk(file,free-8192,KDefaultDrive);
// test change notification when no disk space change
test.Next(_L("test change notification"));
TThreadTask task = ETaskNoChange1;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
TInt64 threshold1=free+gMinFileSize;
TInt64 threshold2=free-gMinFileSize;
TRequestStatus stat1,stat2,stat3;
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1); //more free space becoming available
TheFs.NotifyDiskSpace(threshold2,KDefaultDrive,stat2);
TheFs.NotifyChange(ENotifyAll,stat3);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
RThread thread;
r=thread.Create(_L("thread1"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
TRequestStatus deathStat;
thread.Logon( deathStat );
thread.Resume();
User::After(1000000);
User::WaitForRequest(stat3);
if(!LffsDrive)
test(stat1==KRequestPending && stat2==KRequestPending && stat3==KErrNone);
else
test(stat2==KRequestPending && stat3==KErrNone); //As below
TheFs.NotifyDiskSpaceCancel();
if(!LffsDrive)
test(stat1==KErrCancel && stat2==KErrCancel);
else
test(stat2==KErrCancel); //is invalid for LFFS as can free up space un expectedly
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
// Have three different sessions
// do an operation that will cause the change notification
// and disk change notification to be signalled
test.Next(_L(" test change notification and disk space notification"));
RFs session2,session3;
r=session2.Connect();
test(r==KErrNone);
r=session3.Connect();
test(r==KErrNone);
r=session2.SetSessionPath(gSessionPath);
test(r==KErrNone);
r=session3.SetSessionPath(gSessionPath);
test(r==KErrNone);
task=ETaskFileWrite;
InitialiseForThread(task);
free=FreeDiskSpace(KDefaultDrive);
threshold1=free-400;
TheFs.NotifyDiskSpace(threshold1,KDefaultDrive,stat1);
session2.NotifyChange(ENotifyAll,stat2);
session3.NotifyChange(ENotifyAll,stat3,KTestFile1);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
r=thread.Create(_L("thread2"),ThreadFunction,KStackSize,KHeapSize,KHeapSize,(TAny*)task);
test(r==KErrNone);
thread.Logon( deathStat );
thread.Resume();
User::After(1000000);
User::WaitForRequest(stat1);
User::WaitForRequest(stat2);
User::WaitForRequest(stat3);
test(stat1==KErrNone && stat2==KErrNone && stat3==KErrNone);
free=FreeDiskSpace(KDefaultDrive);
test(free<threshold1);
User::WaitForRequest( deathStat );
thread.Close();
CleanupForThread(task);
// check cancellation of change notification and disk space notification
// on same session
test.Next(_L("test cancellation of notifications"));
TheFs.NotifyDiskSpace(FreeDiskSpace(KDefaultDrive)-512,KDefaultDrive,stat1);
TheFs.NotifyChange(ENotifyAll,stat2);
TheFs.NotifyChange(ENotifyAll,stat3,KTestFile1);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
TheFs.NotifyChangeCancel();
test(stat1==KRequestPending&&stat2==KErrCancel&&stat3==KErrCancel);
TheFs.NotifyDiskSpaceCancel();
test(stat1==KErrCancel);
// request change notification again
TheFs.NotifyDiskSpace(FreeDiskSpace(KDefaultDrive)-512,KDefaultDrive,stat1);
TheFs.NotifyChange(ENotifyAll,stat2);
TheFs.NotifyChange(ENotifyAll,stat3,KTestFile1);
test(stat1==KRequestPending&&stat2==KRequestPending&&stat3==KRequestPending);
TheFs.NotifyDiskSpaceCancel();
test(stat1==KErrCancel&&stat2==KRequestPending&&stat3==KRequestPending);
TheFs.NotifyChangeCancel();
test(stat1==KErrCancel&&stat2==KErrCancel&&stat3==KErrCancel);
session2.Close();
session3.Close();
file.Close();
r=TheFs.Delete(KFileFiller);
test(r==KErrNone);
}
GLDEF_C void CallTestsL()
//
// Do all tests
//
{
TInt r = KErrNone;
TInt driveNumber;
if(IsTestingLFFS())
{
LffsDrive = ETrue;
r = TheFs.CharToDrive( gSessionPath[0], driveNumber );
test( KErrNone == r );
}
// at present internal ram drive not tested - the test should allow for fact
// that memory allocation will affect the free disk space on the internal ram drive
// pc file system c drive is also not tested - the test should allow for the fact
// that other windows processes may affect the free disk space
#ifdef __WINS__
if(gSessionPath[0]==(TText)'C')
#else
// check if gSessionPath drive is RAM drive
TDriveInfo driveInfo;
test(KErrNone == TheFs.CharToDrive(gSessionPath[0], driveNumber));
test(KErrNone == TheFs.Drive(driveInfo, driveNumber));
if(driveInfo.iType == EMediaRam)
#endif
{
#ifdef __WINS__
test.Printf( _L("C:\\ is not tested, test will exit") );
#else
test.Printf( _L("%c:\\ is not tested (is RAM drive), test will exit"), gSessionPath[0]);
#endif
return;
}
//Test uses C drive as secondary drive so test can't be tested on that drive
r = TheFs.CharToDrive(gSessionPath[0], driveNumber);
test(r == KErrNone);
if(driveNumber == EDriveC)
{
test.Printf(_L("Test uses C drive as secondary drive so test can't be test on C drive, test will exit"));
return;
}
Initialise();
TestErrorConditions();
TestCancellation();
TestFunctions();
TestMultiple();
if( !LffsDrive )
{
TestDiskNotify();
}
TestChangeNotification();
if( LffsDrive )
{
TestLffsFunctions();
TestLffsMultiple();
}
}