// 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_hungfs.cpp
// this test will either run with a secure mmc or will simulate a
// mmc card.
//
//
#include <f32file.h>
#include <e32test.h>
#include "t_server.h"
GLDEF_D RTest test(_L("T_HUNGFS"));
GLREF_D RFs TheFs;
LOCAL_D RFile SubFile1;
LOCAL_D TInt HungReturnCodeC;
LOCAL_D RSemaphore HungSemaphoreC;
LOCAL_D TInt HungReturnCodeNC;
LOCAL_D RSemaphore HungSemaphoreNC;
GLREF_C void Format(TInt aDrive);
LOCAL_D const TInt KControlIoLockMount=5;
LOCAL_D const TInt KControlIoClearLockMount=6;
LOCAL_D const TInt KControlIoCNotifier=7;
LOCAL_D const TInt KControlIoClearCNotifier=8;
LOCAL_D const TInt KControlIoCancelNCNotifier=KMaxTInt-1;
LOCAL_D TBool isSecureMmc;
LOCAL_D TFileName gLockedPath;
LOCAL_D TFileName gLockedBase;
LOCAL_D TInt gLockedDrive;
GLREF_D TFileName gSessionPath;
LOCAL_D TInt gSessionDrive;
TBuf8<16> KPassword8=_L8("abc");
TBuf16<8> KPassword=_L("abc");
_LIT(File1,"file1");
_LIT(File2,"file2");
_LIT(Dir1,"\\dir1\\");
_LIT(NotifyDir,"\\not\\");
_LIT(NotifyDir2,"\\abc\\");
_LIT(HungDirNC,"\\hungnc\\");
_LIT(HungDirC,"\\hungc\\");
LOCAL_D const TInt KHeapSize=0x2000;
struct SNonCriticalInfo
{
TBool iSameSession;
TBool iUseRFile;
};
LOCAL_C TInt ThreadFunctionNC(TAny* aInfo)
//
// Thread entry point to put up non-critical notifier
//
{
RFs fs;
TInt r;
TBuf8<8> mmcBuf;
// pad out password if using lockable mmc
if(isSecureMmc)
{
TUint8 pBuf[]={0x61,0x00,0x62,0x00,0x63,00};
mmcBuf.SetLength(6);
for(TInt i=0;i<6;++i)
mmcBuf[i]=pBuf[i];
}
SNonCriticalInfo* info=NULL;
if(aInfo!=NULL)
info=(SNonCriticalInfo*)aInfo;
r=fs.Connect();
if(isSecureMmc)
{
if(info && info->iSameSession)
r=TheFs.LockDrive(gLockedDrive,NULL,mmcBuf,EFalse);
else
{
r=fs.LockDrive(gLockedDrive,NULL,mmcBuf,EFalse);
RDebug::Print(_L("l=%d"),r);
}
}
else
{
if(info && info->iSameSession)
r=TheFs.ControlIo(gLockedDrive,KControlIoLockMount,KPassword8);
else
r=fs.ControlIo(gLockedDrive,KControlIoLockMount,KPassword8);
}
// UserSvr::ForceRemountMedia(ERemovableMedia0);
User::After(300000);
HungSemaphoreNC.Signal();
TFileName hungDir=gLockedBase;
hungDir+=HungDirNC;
if(info && info->iSameSession)
r=TheFs.RmDir(hungDir);
else if(info && info->iSameSession && info->iUseRFile)
{
TBuf8<16> buf=_L8("abc");
r=SubFile1.Write(buf);
}
else
{
r=fs.RmDir(hungDir);
RDebug::Print(_L("rd=%d"),r);
}
HungReturnCodeNC=r;
if(isSecureMmc)
{
r=fs.UnlockDrive(gLockedDrive,mmcBuf,EFalse);
r=fs.ClearPassword(gLockedDrive,mmcBuf);
}
else
r=fs.ControlIo(gLockedDrive,KControlIoClearLockMount,KPassword8);
HungSemaphoreNC.Signal();
fs.Close();
return(KErrNone);
}
LOCAL_C TInt ThreadFunctionC(TAny* aDrive)
//
// Thread entry point to put up a critical notifier
//
{
RFs fs;
TInt r=fs.Connect();
test(r==KErrNone);
TInt drive;
#if defined(__WINS__)
drive=EDriveY;
#else
drive=EDriveC;
#endif
// can only get critcal notifer up using ControIo
// assumes fat file system running on one of the drives named below
r=fs.ControlIo(drive,KControlIoCNotifier);
TBool isRemovable=*(TBool*)aDrive;
TFileName hungDir=(_L("?:"));
#if defined(__WINS__)
if(isRemovable)
hungDir[0]=(TText)('A'+EDriveX);
else
hungDir[0]=(TText)('A'+EDriveY);
#else
if(isRemovable)
hungDir[0]=(TText)('A'+EDriveD);
else
hungDir[0]=(TText)('A'+EDriveC);
#endif
hungDir+=HungDirC;
r=fs.RmDir(hungDir);
r=fs.MkDir(hungDir);
HungReturnCodeC=r;
r=fs.ControlIo(drive,KControlIoClearCNotifier);
HungSemaphoreC.Signal();
r=fs.RmDir(hungDir);
fs.Close();
return(KErrNone);
}
LOCAL_C void PutNonCriticalNotifier(TAny* aInfo,RThread& aThread)
//
// put up a non-critical notifier on a removable media
//
{
TInt r=aThread.Create(_L("ThreadNC"),ThreadFunctionNC,KDefaultStackSize,KMinHeapSize,KMinHeapSize,aInfo);
test(r==KErrNone);
aThread.SetPriority(EPriorityMore);
aThread.Resume();
HungSemaphoreNC.Wait();
User::After(1000000);
}
LOCAL_C void PutCriticalNotifier(TBool aBool,RThread& aThread)
//
// put up a critical notifier on the specified drive
//
{
TInt r=aThread.Create(_L("ThreadC"),ThreadFunctionC,KDefaultStackSize,KMinHeapSize,KMinHeapSize,&aBool);
test(r==KErrNone);
aThread.SetPriority(EPriorityMore);
aThread.Resume();
User::After(1000000);
}
void TestNotifiers()
//
// Test non-critical notifier is cancelled when the critical notifier is put up
// Needs to be carried out on platform with password notifier which handles requests
// asynchronously and uses CAtaDisk in fat file system on c: drive ie. not internal ram
// drive
//
{
test.Next(_L("TestNotifiers"));
if(isSecureMmc)
return;
RThread threadNC,threadC;
PutNonCriticalNotifier(NULL,threadNC);
PutCriticalNotifier(EFalse,threadC);
// get rid of critical notifier
test.Printf(_L("Press cancel on for critcal notifier\n"));
test.Printf(_L("Press any character\n"));
test.Getch();
TRequestStatus deathStat;
threadNC.Logon( deathStat );
HungSemaphoreC.Wait();
// test(HungReturnCodeNC==KErrAbort);
TRequestStatus deathStat2;
threadC.Logon(deathStat2);
HungSemaphoreNC.Wait();
//test(HungReturnCodeNC==KErrLocked);
User::WaitForRequest(deathStat2);
threadNC.Close();
threadC.Close();
}
void TestCriticalFunctions()
//
// test that only a subset of functions are supported when the critical notifier is up
//
{
test.Next(_L("test functions supported with critical notifier"));
// used for EFsSubClose
RFile file;
TInt r=file.Create(TheFs,File1,EFileShareAny|EFileWrite);
test(r==KErrNone||KErrAlreadyExists);
if(r==KErrAlreadyExists)
{
r=file.Open(TheFs,File1,EFileShareAny|EFileWrite);
test(r==KErrNone);
}
TBuf8<16> buf=_L8("abcdefghijklmnop");
r=file.Write(buf);
test(r==KErrNone);
r=TheFs.MkDir(NotifyDir);
test(r==KErrNone);
RThread thread;
PutCriticalNotifier(ETrue,thread);
// test functions that are supported with critical notifier
// EFsNotifyChange
test.Next(_L("test functions that are supported with critical notifier"));
TRequestStatus status;
TheFs.NotifyChange(ENotifyAll,status);
test(status==KRequestPending);
// EFsNotifyChangeCancel
TheFs.NotifyChangeCancel();
test(status==KErrCancel);
// EFsNotifyChangeEx
TheFs.NotifyChange(ENotifyAll,status,gSessionPath);
test(status==KRequestPending);
// EFsNotifyChangeCancelEx
TheFs.NotifyChangeCancel(status);
test(status==KErrCancel);
// EFsSubClose
// difficult to test properly because this does not return an error value
file.Close();
// test that notifications are not completed when a critical notifier completes
test.Next(_L("test notifications not completed"));
TheFs.NotifyChange(ENotifyDisk,status);
test(status==KRequestPending);
TRequestStatus status2;
TheFs.NotifyChange(ENotifyDir,status2,NotifyDir);
test(status2==KRequestPending);
// test some functions that are not supported when critcical notifier up
// EFsFileOpen
test.Next(_L("test functions that are not supported with critical notifier"));
r=file.Open(TheFs,File2,EFileShareAny);
test(r==KErrInUse);
// EFsFileCreate
r=file.Create(TheFs,File2,EFileShareAny);
test(r==KErrInUse);
// EFsMkDir
r=TheFs.MkDir(Dir1);
test(r==KErrInUse);
// EFsVolume
TVolumeInfo info;
r=TheFs.Volume(info,gSessionDrive);
test(r==KErrInUse);
// get rid of critical notifier
test.Printf(_L("Press escape on the critical notifier\n"));
TRequestStatus deathStat;
thread.Logon(deathStat);
HungSemaphoreC.Wait();
test(HungReturnCodeC==KErrAbort);
User::WaitForRequest(deathStat);
thread.Close();
// test notifiers have not gone off
test(status==KRequestPending&&status2==KRequestPending);
// test that notification setup on default drive has had the drive changed
// to * since the critical notifier was up
TFileName notDir=gLockedBase;
notDir+=NotifyDir;
r=TheFs.MkDir(notDir);
test(r==KErrNone);
test(status==KRequestPending&&status2==KErrNone);
TheFs.NotifyChangeCancel();
test(status==KErrCancel);
r=TheFs.Delete(File1);
test(r==KErrNone);
r=TheFs.RmDir(notDir);
test(r==KErrNone);
r=TheFs.RmDir(NotifyDir);
test(r==KErrNone);
}
void TestParsingFunctions()
//
// Test functions that use Parse* and Validate* functions with
// non-critical notifier up
//
{
test.Next(_L("TestParsingFunctions"));
RThread thread;
PutNonCriticalNotifier(NULL,thread);
// test on same drive as notifier
test.Next(_L("test parsing functions on same drive"));
// Using ParseSubst
TFileName dir=gLockedBase;
dir+=Dir1;
TInt r=TheFs.MkDir(dir);
test(r==KErrInUse);
TFileName file=gLockedPath;
file+=File1;
RFile f;
r=f.Create(TheFs,file,EFileShareAny);
test(r==KErrInUse);
// Using ParsePathPtr0
r=TheFs.SetSubst(gLockedPath,EDriveO);
test(r==KErrInUse);
// ValidateDrive
TVolumeInfo info;
r=TheFs.Volume(info,gLockedDrive);
test(r==KErrInUse);
TFileName origSessPath;
r=TheFs.SessionPath(origSessPath);
test(r==KErrNone);
// test these work ok
r=TheFs.SetSessionPath(gLockedPath);
test(r==KErrNone);
r=TheFs.SetSessionPath(origSessPath);
test(r==KErrNone);
// test on different drive from notifier - the session path
test.Next(_L("test parsing functions on a different drive"));
// Using ParseSubst
r=TheFs.MkDir(Dir1);
test(r==KErrNone);
r=TheFs.RmDir(Dir1);
test(r==KErrNone);
r=f.Create(TheFs,File1,EFileShareAny);
test(r==KErrNone);
f.Close();
r=TheFs.Delete(File1);
test(r==KErrNone);
// Using ParsePathPtr0
r=TheFs.SetSubst(gSessionPath,EDriveO);
test(r==KErrNone);
r=TheFs.SetSubst(_L(""),EDriveO);
test(r==KErrNone);
// ValidateDrive
r=TheFs.Volume(info,gSessionDrive);
test(r==KErrNone);
// get rid of non-critical notifier
test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
TRequestStatus deathStat;
thread.Logon( deathStat );
HungSemaphoreNC.Wait();
test(HungReturnCodeNC==KErrNotFound);
User::WaitForRequest( deathStat );
thread.Close();
// test.End();
}
void TestTFsFunctions()
//
// test functions that do not use the Parse* and Validate* functions
//
{
test.Next(_L("TestTFsFunctions"));
TFileName sessName,lockedName;
TInt r=TheFs.FileSystemName(sessName,gSessionDrive);
test(r==KErrNone);
r=TheFs.FileSystemName(lockedName,gLockedDrive);
test(r==KErrNone);
RThread thread;
PutNonCriticalNotifier(NULL,thread);
// test functions on hung drive - should return KErrInUse
test.Next(_L("test TFs functions on hung drive"));
// TFsDismountFileSystem
r=TheFs.DismountFileSystem(lockedName,gLockedDrive);
test(r==KErrInUse);
// TFsMountFileSystem
r=TheFs.MountFileSystem(lockedName,gLockedDrive);
test(r==KErrInUse);
// TFsFileSystemName
r=TheFs.FileSystemName(lockedName,gLockedDrive);
test(r==KErrInUse);
// test functions on drive other than hung drive
test.Next(_L("test TFs functions on drive that is not hung"));
// TFsDismountFileSystem
#if defined(__WINS__)
// bug in TFsMountFileSystem which needs to be fixed before running on EDriveC on WINS
if(gSessionDrive!=EDriveC)
{
#endif
r=TheFs.DismountFileSystem(sessName,gSessionDrive);
test(r==KErrNone);
// TFsMountFileSystem
r=TheFs.MountFileSystem(sessName,gSessionDrive);
test(r==KErrNone);
#if defined(__WINS__)
}
#endif
// TFsFileSystemName
TFileName fsName;
r=TheFs.FileSystemName(fsName,gSessionDrive);
test(r==KErrNone);
test(fsName==sessName);
// test functions that fail on all drives
test.Next(_L("test TFs functions that fail on all drives"));
// TFsListOpenFiles
CFileList* list=NULL;
TOpenFileScan fileScan(TheFs);
TRAP(r,fileScan.NextL(list));
test(r==KErrInUse);
// test functions that should pass on any drive
test.Next(_L("test TFs functions that pass on all drives"));
// TFsSetDefaultPath
// TFsSetSessionPath
r=TheFs.SetSessionPath(gLockedPath);
test(r==KErrNone);
r=TheFs.SetSessionPath(gSessionPath);
test(r==KErrNone);
// get rid of non-critical notifier
test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
TRequestStatus deathStat;
thread.Logon( deathStat );
HungSemaphoreNC.Wait();
test(HungReturnCodeNC==KErrNotFound);
User::WaitForRequest( deathStat );
thread.Close();
// test.End();
}
void TestSubsessions()
//
// test subsession functions
//
{
test.Next(_L("TestSubsessions"));
RThread thread;
PutNonCriticalNotifier(NULL,thread);
// test that subsessions cannot be opened on a hung drive
test.Next(_L("test subsessions cannot be opened on a hung drive"));
// EFsFileCreate
RFile file;
TFileName fileName=gLockedPath;
fileName+=File1;
TInt r=file.Create(TheFs,fileName,EFileShareAny);
test(r==KErrInUse);
// EFsFormatOpen
RFormat format;
TInt count;
r=format.Open(TheFs,gLockedPath,EHighDensity,count);
test(r==KErrInUse);
// EFsDirOpen
RDir dir;
r=dir.Open(TheFs,gLockedPath,KEntryAttMaskSupported);
test(r==KErrInUse);
// EFsRawDiskOpen
RRawDisk raw;
r=raw.Open(TheFs,gLockedDrive);
test(r==KErrInUse);
// get rid of non-critical notifier
test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
TRequestStatus deathStat;
thread.Logon( deathStat );
HungSemaphoreNC.Wait();
test(HungReturnCodeNC==KErrNotFound);
User::WaitForRequest( deathStat );
thread.Close();
// now open the subsessions
r=file.Create(TheFs,fileName,EFileShareAny);
test(r==KErrNone||KErrAlreadyExists);
if(r==KErrAlreadyExists)
{
r=file.Open(TheFs,fileName,EFileShareAny);
test(r==KErrNone);
}
r=dir.Open(TheFs,gLockedPath,KEntryAttMaskSupported);
test(r==KErrNone);
// put notifier back up
PutNonCriticalNotifier(NULL,thread);
// test subsession operations fail on a hung drive
test.Next(_L("test subsession operations fail on a hung drive"));
// EFsFileRead
TBuf8<16> readBuf;
r=file.Read(readBuf);
test(r==KErrInUse);
// subsession should be able to be closed ok
file.Close();
// EFsDelete
r=TheFs.Delete(fileName);
test(r==KErrInUse);
// EFsDirRead
TEntry entry;
r=dir.Read(entry);
test(r==KErrInUse);
// subsession should be able to be closed ok
dir.Close();
// not going to test operations on a drive the is not hung
// since this will be tested on other tests
// get rid of non-critical notifier
test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
thread.Logon( deathStat );
HungSemaphoreNC.Wait();
test(HungReturnCodeNC==KErrNotFound);
User::WaitForRequest( deathStat );
thread.Close();
r=TheFs.Delete(fileName);
test(r==KErrNone);
// test.End();
}
void TestSameSession()
//
// Test functions that can and cannot be handled from same session when notifier is up
//
{
test.Next(_L("TestSameSession"));
RFile file;
TInt r=file.Create(TheFs,File1,EFileWrite);
test(r==KErrNone);
// put notifier up using TheFs session
SNonCriticalInfo info={ETrue,0};
RThread thread;
PutNonCriticalNotifier(&info,thread);
// test critical functions can be handled
test.Next(_L("test critical functions can be handled"));
// EFsNotifyChange
TRequestStatus status;
TheFs.NotifyChange(ENotifyAll,status);
test(status==KRequestPending);
// EFsNotifyChangeCancel
TheFs.NotifyChangeCancel();
test(status==KErrCancel);
// EFsNotifyChange again
TheFs.NotifyChange(ENotifyAll,status);
test(status==KRequestPending);
// EFsNotifyChangeCancelEx
TheFs.NotifyChangeCancel(status);
test(status==KErrCancel);
// not going to test EFsSubClose
// test other functions are not handled
test.Next(_L("test other functions cannot be handled"));
// EFsNotifyChangeEx
TheFs.NotifyChange(ENotifyAll,status,gSessionPath);
test(status==KErrInUse);
TFileName defPath;
// EFsCheckDisk
r=TheFs.CheckDisk(gSessionPath);
test(r==KErrInUse);
// EFsFileWrite
_LIT8(buffer,"abc");
TBuf8<8> buf(buffer);
r=file.Write(buf);
test(r==KErrInUse);
// this file should be able to be closed
file.Close();
// get rid of non-critical notifier
test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
TRequestStatus deathStat;
thread.Logon( deathStat );
HungSemaphoreNC.Wait();
test(HungReturnCodeNC==KErrNotFound);
User::WaitForRequest( deathStat );
thread.Close();
r=TheFs.Delete(File1);
test(r==KErrNone);
// test.End();
}
void TestSameSubSession()
//
// test hung file server with same subsession
//
{
_LIT(file1Name,"\\SubFile1");
_LIT(file2Name,"\\SubFile2");
_LIT(file3Name,"\\SubFile3");
_LIT(file4Name,"\\SubFile4");
TFileName origSession;
TInt r=TheFs.SessionPath(origSession);
test(r==KErrNone);
TFileName file1Path(gLockedBase);
file1Path+=file1Name;
TFileName file2Path(file2Name);
TFileName file3Path(gLockedBase);
file3Path+=file3Name;
TFileName file4Path(file4Name);
// create file that will be used to hang file server
r=SubFile1.Create(TheFs,file1Path,EFileWrite);
test(r==KErrNone);
// create file with same session but on different drive
RFile subfile2;
r=subfile2.Create(TheFs,file2Path,EFileWrite);
test(r==KErrNone);
// create file on unhung drive and with different session
RFs fs2;
r=fs2.Connect();
test(r==KErrNone);
r=fs2.SetSessionPath(origSession);
test(r==KErrNone);
RFile subfile3;
r=subfile3.Create(fs2,file3Path,EFileWrite);
test(r==KErrNone);
// create file on unhung drive and with different session
RFile subfile4;
r=subfile4.Create(fs2,file4Path,EFileWrite);
test(r==KErrNone);
// in a different thread cause the server to hang using one of the File1 subsession
// put notifier up using TheFs session
SNonCriticalInfo info={ETrue,ETrue};
RThread thread;
PutNonCriticalNotifier(&info,thread);
test.Next(_L("test writing to files with hung file server"));
// check only file4 can be written to
_LIT8(buffer,"abc");
TBuf8<8> buf(buffer);
// File1 caused hung file server
r=SubFile1.Write(buf);
test(r==KErrInUse);
// file2 is same session as subsession that caused hung file server
r=subfile2.Write(buf);
test(r==KErrInUse);
// file3 is opened on hung drive
r=subfile3.Write(buf);
test(r==KErrInUse);
// file4 should be ok
r=subfile4.Write(buf);
test(r==KErrNone);
// hard to test EFsSubClose since does not return an error value
test.Next(_L("test closing down the subsessions"));
subfile4.Close();
// calling close on the same subsession as is hung will cause this subsession
// to be closed once the original request is completed
SubFile1.Close();
subfile2.Close();
// get rid of non-critical notifier
test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
TRequestStatus deathStat;
thread.Logon( deathStat );
HungSemaphoreNC.Wait();
test(HungReturnCodeNC==KErrNotFound);
User::WaitForRequest( deathStat );
thread.Close();
// close remaining files
subfile3.Close();
// clean up
fs2.Close();
r=TheFs.Delete(file1Path);
test(r==KErrNone);
r=TheFs.Delete(file2Path);
test(r==KErrNone);
r=TheFs.Delete(file3Path);
test(r==KErrNone);
r=TheFs.Delete(file4Path);
test(r==KErrNone);
}
void TestExtendedNotifier()
//
//
//
{
test.Next(_L("TestExtendedNotifier"));
// setup a notification on a removable media
test.Next(_L("test with drive specified"));
TFileName notDir=gLockedBase;
notDir+=NotifyDir;
TRequestStatus status;
TheFs.NotifyChange(ENotifyAll,status,notDir);
test(status==KRequestPending);
// now do an operation on c: and test no notification
TInt r=TheFs.MkDir(NotifyDir);
test(r==KErrNone);
r=TheFs.RmDir(NotifyDir);
test(r==KErrNone);
User::After(1000000);
test(status==KRequestPending);
TheFs.NotifyChangeCancel(status);
test(status==KErrCancel);
// now put up the notifier
RThread thread;
PutNonCriticalNotifier(NULL,thread);
// repeat the above notification
// setup a notification on a removable media - the drive should be changed
// to * since notifier is up
test.Next(_L("test with wildcard for drive"));
TheFs.NotifyChange(ENotifyAll,status,notDir);
test(status==KRequestPending);
// test notification does not go off with wrong path
r=TheFs.MkDir(NotifyDir2);
test(r==KErrNone);
r=TheFs.RmDir(NotifyDir2);
test(r==KErrNone);
test(status==KRequestPending);
// now do an operation on c: and test there has been a notification
r=TheFs.MkDir(NotifyDir);
test(r==KErrNone);
r=TheFs.RmDir(NotifyDir);
test(r==KErrNone);
User::After(1000000);
// request should be completed this time
test(status==KErrNone);
// set up a notification on drive that is not removable
// the path should not be changed
test.Next(_L("test with non-removable drive"));
TheFs.NotifyChange(ENotifyAll,status,notDir);
test(status==KRequestPending);
TRequestStatus status2;
TFileName origSession;
r=TheFs.SessionPath(origSession);
test(r==KErrNone);
RFs fs2;
r=fs2.Connect();
test(r==KErrNone);
r=fs2.SetSessionPath(origSession);
test(r==KErrNone);
_LIT(notifyDirZ,"z:\\test\\");
_LIT(notifyDirSess,"\\test\\");
// notifyDirZ already exists, create test dir in session path
r=fs2.MkDir(notifyDirSess);
test(r==KErrNone);
fs2.NotifyChange(ENotifyDir,status2,notifyDirZ);
test(status2==KRequestPending);
TRequestStatus status3;
fs2.NotifyChange(ENotifyDir,status3,notifyDirSess);
test(status3==KRequestPending);
// now delete session dir and test no notification
r=TheFs.RmDir(notifyDirSess);
test(r==KErrNone);
test(status2==KRequestPending && status3==KErrNone);
// get rid of non-critical notifier
test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
TRequestStatus deathStat;
thread.Logon( deathStat );
HungSemaphoreNC.Wait();
test(HungReturnCodeNC==KErrNotFound);
User::WaitForRequest( deathStat );
thread.Close();
test(status==KErrNone&&status2==KErrNone);
fs2.Close();
test.Next(_L("test extended notification with critical notifier"));
RThread threadC;
// put a a critical notifier
PutCriticalNotifier(ETrue,threadC);
// setup extended change notification on session path, drive should be changed to *
TheFs.NotifyChange(ENotifyAll,status,NotifyDir);
test(status==KRequestPending);
// get rid of notifier
test.Printf(_L("Press cancel on for critcal notifier\n"));
threadC.Logon(deathStat);
HungSemaphoreC.Wait();
User::WaitForRequest(deathStat);
threadC.Close();
// test that notification has not gone off
test(status==KRequestPending);
// create directory on locked drive
r=TheFs.MkDir(notDir);
test(r==KErrNone);
// test notifier goes off
test(status==KErrNone);
r=TheFs.RmDir(notDir);
test(r==KErrNone);
// get rid of critical notifier
}
LOCAL_C TBool TestSessionPath()
//
//
//
{
#if defined(__WINS__)
TInt r=TheFs.CharToDrive(gSessionPath[0],gSessionDrive);
test(r==KErrNone);
if(gSessionDrive==EDriveX)
return(EFalse);
#else
TInt r=TheFs.CharToDrive(gSessionPath[0],gSessionDrive);
test(r==KErrNone);
TDriveList list;
r=TheFs.DriveList(list);
test(r==KErrNone);
if((list[gSessionDrive])&KDriveAttRemovable)
return(EFalse);
#endif
return(ETrue);
}
GLDEF_C void CallTestsL()
//
// Test a hung file server
//
{
if(!IsTestTypeStandard())
return;
if(!TestSessionPath())
{
test.Printf(_L("Not testing on %S\n"),&gSessionPath);
return;
}
#if defined(__WINS__)
gLockedDrive=EDriveX;
gLockedPath=_L("?:\\");
gLockedBase=_L("?:");
gLockedPath[0]=gLockedBase[0]=(TText)('A'+gLockedDrive);
#else
gLockedDrive=EDriveD;
gLockedPath=_L("?:\\");
gLockedBase=_L("?:");
gLockedPath[0]=gLockedBase[0]=(TText)('A'+gLockedDrive);
#endif
test.Printf(_L("Is a secure mmc present? Press y for yes\n"));
TChar c=test.Getch();
if(c=='y'||c=='Y')
isSecureMmc=ETrue;
else
isSecureMmc=EFalse;
TInt r=HungSemaphoreC.CreateLocal(0);
test(r==KErrNone);
r=HungSemaphoreNC.CreateLocal(0);
test(r==KErrNone);
// create sharable session
TheFs.ShareAuto();
TestParsingFunctions();
TestTFsFunctions();
TestExtendedNotifier();
TestSubsessions();
// TestNotifiers();
TestCriticalFunctions();
TestSameSession();
TestSameSubSession();
HungSemaphoreC.Close();
HungSemaphoreNC.Close();
}