--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/server/t_hungfs.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,926 @@
+// 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();
+}