First public contribution.
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32test\server\t_hungfs.cpp
15 // this test will either run with a secure mmc or will simulate a
25 GLDEF_D RTest test(_L("T_HUNGFS"));
28 LOCAL_D RFile SubFile1;
29 LOCAL_D TInt HungReturnCodeC;
31 LOCAL_D RSemaphore HungSemaphoreC;
32 LOCAL_D TInt HungReturnCodeNC;
33 LOCAL_D RSemaphore HungSemaphoreNC;
35 GLREF_C void Format(TInt aDrive);
37 LOCAL_D const TInt KControlIoLockMount=5;
38 LOCAL_D const TInt KControlIoClearLockMount=6;
39 LOCAL_D const TInt KControlIoCNotifier=7;
40 LOCAL_D const TInt KControlIoClearCNotifier=8;
42 LOCAL_D const TInt KControlIoCancelNCNotifier=KMaxTInt-1;
44 LOCAL_D TBool isSecureMmc;
45 LOCAL_D TFileName gLockedPath;
46 LOCAL_D TFileName gLockedBase;
47 LOCAL_D TInt gLockedDrive;
48 GLREF_D TFileName gSessionPath;
49 LOCAL_D TInt gSessionDrive;
51 TBuf8<16> KPassword8=_L8("abc");
52 TBuf16<8> KPassword=_L("abc");
55 _LIT(Dir1,"\\dir1\\");
56 _LIT(NotifyDir,"\\not\\");
57 _LIT(NotifyDir2,"\\abc\\");
58 _LIT(HungDirNC,"\\hungnc\\");
59 _LIT(HungDirC,"\\hungc\\");
61 LOCAL_D const TInt KHeapSize=0x2000;
63 struct SNonCriticalInfo
69 LOCAL_C TInt ThreadFunctionNC(TAny* aInfo)
71 // Thread entry point to put up non-critical notifier
78 // pad out password if using lockable mmc
81 TUint8 pBuf[]={0x61,0x00,0x62,0x00,0x63,00};
87 SNonCriticalInfo* info=NULL;
89 info=(SNonCriticalInfo*)aInfo;
95 if(info && info->iSameSession)
96 r=TheFs.LockDrive(gLockedDrive,NULL,mmcBuf,EFalse);
99 r=fs.LockDrive(gLockedDrive,NULL,mmcBuf,EFalse);
100 RDebug::Print(_L("l=%d"),r);
105 if(info && info->iSameSession)
106 r=TheFs.ControlIo(gLockedDrive,KControlIoLockMount,KPassword8);
108 r=fs.ControlIo(gLockedDrive,KControlIoLockMount,KPassword8);
110 // UserSvr::ForceRemountMedia(ERemovableMedia0);
112 HungSemaphoreNC.Signal();
114 TFileName hungDir=gLockedBase;
116 if(info && info->iSameSession)
117 r=TheFs.RmDir(hungDir);
118 else if(info && info->iSameSession && info->iUseRFile)
120 TBuf8<16> buf=_L8("abc");
121 r=SubFile1.Write(buf);
126 RDebug::Print(_L("rd=%d"),r);
132 r=fs.UnlockDrive(gLockedDrive,mmcBuf,EFalse);
133 r=fs.ClearPassword(gLockedDrive,mmcBuf);
136 r=fs.ControlIo(gLockedDrive,KControlIoClearLockMount,KPassword8);
138 HungSemaphoreNC.Signal();
145 LOCAL_C TInt ThreadFunctionC(TAny* aDrive)
147 // Thread entry point to put up a critical notifier
155 #if defined(__WINS__)
160 // can only get critcal notifer up using ControIo
161 // assumes fat file system running on one of the drives named below
162 r=fs.ControlIo(drive,KControlIoCNotifier);
164 TBool isRemovable=*(TBool*)aDrive;
165 TFileName hungDir=(_L("?:"));
166 #if defined(__WINS__)
168 hungDir[0]=(TText)('A'+EDriveX);
170 hungDir[0]=(TText)('A'+EDriveY);
173 hungDir[0]=(TText)('A'+EDriveD);
175 hungDir[0]=(TText)('A'+EDriveC);
182 r=fs.ControlIo(drive,KControlIoClearCNotifier);
184 HungSemaphoreC.Signal();
190 LOCAL_C void PutNonCriticalNotifier(TAny* aInfo,RThread& aThread)
192 // put up a non-critical notifier on a removable media
195 TInt r=aThread.Create(_L("ThreadNC"),ThreadFunctionNC,KDefaultStackSize,KMinHeapSize,KMinHeapSize,aInfo);
197 aThread.SetPriority(EPriorityMore);
199 HungSemaphoreNC.Wait();
200 User::After(1000000);
204 LOCAL_C void PutCriticalNotifier(TBool aBool,RThread& aThread)
206 // put up a critical notifier on the specified drive
209 TInt r=aThread.Create(_L("ThreadC"),ThreadFunctionC,KDefaultStackSize,KMinHeapSize,KMinHeapSize,&aBool);
211 aThread.SetPriority(EPriorityMore);
213 User::After(1000000);
218 // Test non-critical notifier is cancelled when the critical notifier is put up
219 // Needs to be carried out on platform with password notifier which handles requests
220 // asynchronously and uses CAtaDisk in fat file system on c: drive ie. not internal ram
224 test.Next(_L("TestNotifiers"));
227 RThread threadNC,threadC;
228 PutNonCriticalNotifier(NULL,threadNC);
229 PutCriticalNotifier(EFalse,threadC);
230 // get rid of critical notifier
231 test.Printf(_L("Press cancel on for critcal notifier\n"));
232 test.Printf(_L("Press any character\n"));
234 TRequestStatus deathStat;
235 threadNC.Logon( deathStat );
236 HungSemaphoreC.Wait();
237 // test(HungReturnCodeNC==KErrAbort);
238 TRequestStatus deathStat2;
239 threadC.Logon(deathStat2);
240 HungSemaphoreNC.Wait();
241 //test(HungReturnCodeNC==KErrLocked);
242 User::WaitForRequest(deathStat2);
247 void TestCriticalFunctions()
249 // test that only a subset of functions are supported when the critical notifier is up
252 test.Next(_L("test functions supported with critical notifier"));
253 // used for EFsSubClose
255 TInt r=file.Create(TheFs,File1,EFileShareAny|EFileWrite);
256 test(r==KErrNone||KErrAlreadyExists);
257 if(r==KErrAlreadyExists)
259 r=file.Open(TheFs,File1,EFileShareAny|EFileWrite);
262 TBuf8<16> buf=_L8("abcdefghijklmnop");
266 r=TheFs.MkDir(NotifyDir);
270 PutCriticalNotifier(ETrue,thread);
272 // test functions that are supported with critical notifier
274 test.Next(_L("test functions that are supported with critical notifier"));
275 TRequestStatus status;
276 TheFs.NotifyChange(ENotifyAll,status);
277 test(status==KRequestPending);
278 // EFsNotifyChangeCancel
279 TheFs.NotifyChangeCancel();
280 test(status==KErrCancel);
282 TheFs.NotifyChange(ENotifyAll,status,gSessionPath);
283 test(status==KRequestPending);
284 // EFsNotifyChangeCancelEx
285 TheFs.NotifyChangeCancel(status);
286 test(status==KErrCancel);
288 // difficult to test properly because this does not return an error value
291 // test that notifications are not completed when a critical notifier completes
292 test.Next(_L("test notifications not completed"));
293 TheFs.NotifyChange(ENotifyDisk,status);
294 test(status==KRequestPending);
295 TRequestStatus status2;
296 TheFs.NotifyChange(ENotifyDir,status2,NotifyDir);
297 test(status2==KRequestPending);
299 // test some functions that are not supported when critcical notifier up
301 test.Next(_L("test functions that are not supported with critical notifier"));
302 r=file.Open(TheFs,File2,EFileShareAny);
305 r=file.Create(TheFs,File2,EFileShareAny);
312 r=TheFs.Volume(info,gSessionDrive);
315 // get rid of critical notifier
316 test.Printf(_L("Press escape on the critical notifier\n"));
317 TRequestStatus deathStat;
318 thread.Logon(deathStat);
319 HungSemaphoreC.Wait();
320 test(HungReturnCodeC==KErrAbort);
321 User::WaitForRequest(deathStat);
324 // test notifiers have not gone off
325 test(status==KRequestPending&&status2==KRequestPending);
327 // test that notification setup on default drive has had the drive changed
328 // to * since the critical notifier was up
329 TFileName notDir=gLockedBase;
331 r=TheFs.MkDir(notDir);
333 test(status==KRequestPending&&status2==KErrNone);
334 TheFs.NotifyChangeCancel();
335 test(status==KErrCancel);
336 r=TheFs.Delete(File1);
338 r=TheFs.RmDir(notDir);
340 r=TheFs.RmDir(NotifyDir);
344 void TestParsingFunctions()
346 // Test functions that use Parse* and Validate* functions with
347 // non-critical notifier up
350 test.Next(_L("TestParsingFunctions"));
352 PutNonCriticalNotifier(NULL,thread);
354 // test on same drive as notifier
355 test.Next(_L("test parsing functions on same drive"));
357 TFileName dir=gLockedBase;
359 TInt r=TheFs.MkDir(dir);
361 TFileName file=gLockedPath;
364 r=f.Create(TheFs,file,EFileShareAny);
366 // Using ParsePathPtr0
367 r=TheFs.SetSubst(gLockedPath,EDriveO);
371 r=TheFs.Volume(info,gLockedDrive);
374 TFileName origSessPath;
375 r=TheFs.SessionPath(origSessPath);
378 // test these work ok
379 r=TheFs.SetSessionPath(gLockedPath);
381 r=TheFs.SetSessionPath(origSessPath);
384 // test on different drive from notifier - the session path
385 test.Next(_L("test parsing functions on a different drive"));
391 r=f.Create(TheFs,File1,EFileShareAny);
394 r=TheFs.Delete(File1);
396 // Using ParsePathPtr0
397 r=TheFs.SetSubst(gSessionPath,EDriveO);
399 r=TheFs.SetSubst(_L(""),EDriveO);
402 r=TheFs.Volume(info,gSessionDrive);
405 // get rid of non-critical notifier
406 test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
408 TRequestStatus deathStat;
409 thread.Logon( deathStat );
410 HungSemaphoreNC.Wait();
411 test(HungReturnCodeNC==KErrNotFound);
412 User::WaitForRequest( deathStat );
418 void TestTFsFunctions()
420 // test functions that do not use the Parse* and Validate* functions
423 test.Next(_L("TestTFsFunctions"));
424 TFileName sessName,lockedName;
425 TInt r=TheFs.FileSystemName(sessName,gSessionDrive);
427 r=TheFs.FileSystemName(lockedName,gLockedDrive);
431 PutNonCriticalNotifier(NULL,thread);
433 // test functions on hung drive - should return KErrInUse
434 test.Next(_L("test TFs functions on hung drive"));
435 // TFsDismountFileSystem
436 r=TheFs.DismountFileSystem(lockedName,gLockedDrive);
438 // TFsMountFileSystem
439 r=TheFs.MountFileSystem(lockedName,gLockedDrive);
442 r=TheFs.FileSystemName(lockedName,gLockedDrive);
445 // test functions on drive other than hung drive
446 test.Next(_L("test TFs functions on drive that is not hung"));
447 // TFsDismountFileSystem
448 #if defined(__WINS__)
449 // bug in TFsMountFileSystem which needs to be fixed before running on EDriveC on WINS
450 if(gSessionDrive!=EDriveC)
453 r=TheFs.DismountFileSystem(sessName,gSessionDrive);
455 // TFsMountFileSystem
456 r=TheFs.MountFileSystem(sessName,gSessionDrive);
458 #if defined(__WINS__)
463 r=TheFs.FileSystemName(fsName,gSessionDrive);
465 test(fsName==sessName);
467 // test functions that fail on all drives
468 test.Next(_L("test TFs functions that fail on all drives"));
470 CFileList* list=NULL;
471 TOpenFileScan fileScan(TheFs);
472 TRAP(r,fileScan.NextL(list));
475 // test functions that should pass on any drive
476 test.Next(_L("test TFs functions that pass on all drives"));
479 r=TheFs.SetSessionPath(gLockedPath);
481 r=TheFs.SetSessionPath(gSessionPath);
484 // get rid of non-critical notifier
485 test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
486 TRequestStatus deathStat;
487 thread.Logon( deathStat );
488 HungSemaphoreNC.Wait();
489 test(HungReturnCodeNC==KErrNotFound);
490 User::WaitForRequest( deathStat );
496 void TestSubsessions()
498 // test subsession functions
501 test.Next(_L("TestSubsessions"));
503 PutNonCriticalNotifier(NULL,thread);
505 // test that subsessions cannot be opened on a hung drive
506 test.Next(_L("test subsessions cannot be opened on a hung drive"));
509 TFileName fileName=gLockedPath;
511 TInt r=file.Create(TheFs,fileName,EFileShareAny);
516 r=format.Open(TheFs,gLockedPath,EHighDensity,count);
520 r=dir.Open(TheFs,gLockedPath,KEntryAttMaskSupported);
524 r=raw.Open(TheFs,gLockedDrive);
527 // get rid of non-critical notifier
528 test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
529 TRequestStatus deathStat;
530 thread.Logon( deathStat );
531 HungSemaphoreNC.Wait();
532 test(HungReturnCodeNC==KErrNotFound);
533 User::WaitForRequest( deathStat );
536 // now open the subsessions
537 r=file.Create(TheFs,fileName,EFileShareAny);
538 test(r==KErrNone||KErrAlreadyExists);
539 if(r==KErrAlreadyExists)
541 r=file.Open(TheFs,fileName,EFileShareAny);
544 r=dir.Open(TheFs,gLockedPath,KEntryAttMaskSupported);
547 // put notifier back up
548 PutNonCriticalNotifier(NULL,thread);
550 // test subsession operations fail on a hung drive
551 test.Next(_L("test subsession operations fail on a hung drive"));
554 r=file.Read(readBuf);
556 // subsession should be able to be closed ok
559 r=TheFs.Delete(fileName);
565 // subsession should be able to be closed ok
568 // not going to test operations on a drive the is not hung
569 // since this will be tested on other tests
571 // get rid of non-critical notifier
572 test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
573 thread.Logon( deathStat );
574 HungSemaphoreNC.Wait();
575 test(HungReturnCodeNC==KErrNotFound);
576 User::WaitForRequest( deathStat );
579 r=TheFs.Delete(fileName);
584 void TestSameSession()
586 // Test functions that can and cannot be handled from same session when notifier is up
589 test.Next(_L("TestSameSession"));
592 TInt r=file.Create(TheFs,File1,EFileWrite);
595 // put notifier up using TheFs session
596 SNonCriticalInfo info={ETrue,0};
598 PutNonCriticalNotifier(&info,thread);
600 // test critical functions can be handled
601 test.Next(_L("test critical functions can be handled"));
603 TRequestStatus status;
604 TheFs.NotifyChange(ENotifyAll,status);
605 test(status==KRequestPending);
606 // EFsNotifyChangeCancel
607 TheFs.NotifyChangeCancel();
608 test(status==KErrCancel);
609 // EFsNotifyChange again
610 TheFs.NotifyChange(ENotifyAll,status);
611 test(status==KRequestPending);
612 // EFsNotifyChangeCancelEx
613 TheFs.NotifyChangeCancel(status);
614 test(status==KErrCancel);
615 // not going to test EFsSubClose
617 // test other functions are not handled
618 test.Next(_L("test other functions cannot be handled"));
620 TheFs.NotifyChange(ENotifyAll,status,gSessionPath);
621 test(status==KErrInUse);
624 r=TheFs.CheckDisk(gSessionPath);
628 TBuf8<8> buf(buffer);
632 // this file should be able to be closed
635 // get rid of non-critical notifier
636 test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
638 TRequestStatus deathStat;
639 thread.Logon( deathStat );
640 HungSemaphoreNC.Wait();
641 test(HungReturnCodeNC==KErrNotFound);
642 User::WaitForRequest( deathStat );
645 r=TheFs.Delete(File1);
650 void TestSameSubSession()
652 // test hung file server with same subsession
655 _LIT(file1Name,"\\SubFile1");
656 _LIT(file2Name,"\\SubFile2");
657 _LIT(file3Name,"\\SubFile3");
658 _LIT(file4Name,"\\SubFile4");
659 TFileName origSession;
660 TInt r=TheFs.SessionPath(origSession);
662 TFileName file1Path(gLockedBase);
663 file1Path+=file1Name;
664 TFileName file2Path(file2Name);
665 TFileName file3Path(gLockedBase);
666 file3Path+=file3Name;
667 TFileName file4Path(file4Name);
668 // create file that will be used to hang file server
669 r=SubFile1.Create(TheFs,file1Path,EFileWrite);
671 // create file with same session but on different drive
673 r=subfile2.Create(TheFs,file2Path,EFileWrite);
675 // create file on unhung drive and with different session
679 r=fs2.SetSessionPath(origSession);
682 r=subfile3.Create(fs2,file3Path,EFileWrite);
684 // create file on unhung drive and with different session
686 r=subfile4.Create(fs2,file4Path,EFileWrite);
688 // in a different thread cause the server to hang using one of the File1 subsession
689 // put notifier up using TheFs session
690 SNonCriticalInfo info={ETrue,ETrue};
692 PutNonCriticalNotifier(&info,thread);
693 test.Next(_L("test writing to files with hung file server"));
694 // check only file4 can be written to
696 TBuf8<8> buf(buffer);
697 // File1 caused hung file server
698 r=SubFile1.Write(buf);
700 // file2 is same session as subsession that caused hung file server
701 r=subfile2.Write(buf);
703 // file3 is opened on hung drive
704 r=subfile3.Write(buf);
706 // file4 should be ok
707 r=subfile4.Write(buf);
709 // hard to test EFsSubClose since does not return an error value
710 test.Next(_L("test closing down the subsessions"));
712 // calling close on the same subsession as is hung will cause this subsession
713 // to be closed once the original request is completed
717 // get rid of non-critical notifier
718 test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
719 TRequestStatus deathStat;
720 thread.Logon( deathStat );
721 HungSemaphoreNC.Wait();
722 test(HungReturnCodeNC==KErrNotFound);
723 User::WaitForRequest( deathStat );
725 // close remaining files
729 r=TheFs.Delete(file1Path);
731 r=TheFs.Delete(file2Path);
733 r=TheFs.Delete(file3Path);
735 r=TheFs.Delete(file4Path);
739 void TestExtendedNotifier()
744 test.Next(_L("TestExtendedNotifier"));
745 // setup a notification on a removable media
746 test.Next(_L("test with drive specified"));
747 TFileName notDir=gLockedBase;
749 TRequestStatus status;
750 TheFs.NotifyChange(ENotifyAll,status,notDir);
751 test(status==KRequestPending);
752 // now do an operation on c: and test no notification
753 TInt r=TheFs.MkDir(NotifyDir);
755 r=TheFs.RmDir(NotifyDir);
757 User::After(1000000);
758 test(status==KRequestPending);
759 TheFs.NotifyChangeCancel(status);
760 test(status==KErrCancel);
762 // now put up the notifier
764 PutNonCriticalNotifier(NULL,thread);
766 // repeat the above notification
767 // setup a notification on a removable media - the drive should be changed
768 // to * since notifier is up
769 test.Next(_L("test with wildcard for drive"));
770 TheFs.NotifyChange(ENotifyAll,status,notDir);
771 test(status==KRequestPending);
772 // test notification does not go off with wrong path
773 r=TheFs.MkDir(NotifyDir2);
775 r=TheFs.RmDir(NotifyDir2);
777 test(status==KRequestPending);
778 // now do an operation on c: and test there has been a notification
779 r=TheFs.MkDir(NotifyDir);
781 r=TheFs.RmDir(NotifyDir);
783 User::After(1000000);
784 // request should be completed this time
785 test(status==KErrNone);
787 // set up a notification on drive that is not removable
788 // the path should not be changed
789 test.Next(_L("test with non-removable drive"));
790 TheFs.NotifyChange(ENotifyAll,status,notDir);
791 test(status==KRequestPending);
792 TRequestStatus status2;
793 TFileName origSession;
794 r=TheFs.SessionPath(origSession);
799 r=fs2.SetSessionPath(origSession);
801 _LIT(notifyDirZ,"z:\\test\\");
802 _LIT(notifyDirSess,"\\test\\");
803 // notifyDirZ already exists, create test dir in session path
804 r=fs2.MkDir(notifyDirSess);
806 fs2.NotifyChange(ENotifyDir,status2,notifyDirZ);
807 test(status2==KRequestPending);
808 TRequestStatus status3;
809 fs2.NotifyChange(ENotifyDir,status3,notifyDirSess);
810 test(status3==KRequestPending);
811 // now delete session dir and test no notification
812 r=TheFs.RmDir(notifyDirSess);
814 test(status2==KRequestPending && status3==KErrNone);
816 // get rid of non-critical notifier
817 test.Printf(_L("Enter %S on the notifier\n"),&KPassword);
818 TRequestStatus deathStat;
819 thread.Logon( deathStat );
820 HungSemaphoreNC.Wait();
821 test(HungReturnCodeNC==KErrNotFound);
822 User::WaitForRequest( deathStat );
824 test(status==KErrNone&&status2==KErrNone);
827 test.Next(_L("test extended notification with critical notifier"));
829 // put a a critical notifier
830 PutCriticalNotifier(ETrue,threadC);
831 // setup extended change notification on session path, drive should be changed to *
832 TheFs.NotifyChange(ENotifyAll,status,NotifyDir);
833 test(status==KRequestPending);
834 // get rid of notifier
835 test.Printf(_L("Press cancel on for critcal notifier\n"));
836 threadC.Logon(deathStat);
837 HungSemaphoreC.Wait();
838 User::WaitForRequest(deathStat);
840 // test that notification has not gone off
841 test(status==KRequestPending);
842 // create directory on locked drive
843 r=TheFs.MkDir(notDir);
845 // test notifier goes off
846 test(status==KErrNone);
847 r=TheFs.RmDir(notDir);
849 // get rid of critical notifier
852 LOCAL_C TBool TestSessionPath()
857 #if defined(__WINS__)
858 TInt r=TheFs.CharToDrive(gSessionPath[0],gSessionDrive);
860 if(gSessionDrive==EDriveX)
863 TInt r=TheFs.CharToDrive(gSessionPath[0],gSessionDrive);
866 r=TheFs.DriveList(list);
868 if((list[gSessionDrive])&KDriveAttRemovable)
875 GLDEF_C void CallTestsL()
877 // Test a hung file server
880 if(!IsTestTypeStandard())
883 if(!TestSessionPath())
885 test.Printf(_L("Not testing on %S\n"),&gSessionPath);
888 #if defined(__WINS__)
889 gLockedDrive=EDriveX;
890 gLockedPath=_L("?:\\");
891 gLockedBase=_L("?:");
892 gLockedPath[0]=gLockedBase[0]=(TText)('A'+gLockedDrive);
894 gLockedDrive=EDriveD;
895 gLockedPath=_L("?:\\");
896 gLockedBase=_L("?:");
897 gLockedPath[0]=gLockedBase[0]=(TText)('A'+gLockedDrive);
900 test.Printf(_L("Is a secure mmc present? Press y for yes\n"));
901 TChar c=test.Getch();
907 TInt r=HungSemaphoreC.CreateLocal(0);
909 r=HungSemaphoreNC.CreateLocal(0);
912 // create sharable session
915 TestParsingFunctions();
917 TestExtendedNotifier();
920 TestCriticalFunctions();
922 TestSameSubSession();
924 HungSemaphoreC.Close();
925 HungSemaphoreNC.Close();