Update contrib.
1 // Copyright (c) 1996-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_mount.cpp
15 // Testing some issues connected with mounting/dismounting file fystems, drives finalisation etc.
23 #define __E32TEST_EXTENSION__
28 #include <e32property.h>
32 #include "fat_utils.h"
34 using namespace Fat_Test_Utils;
37 // Solve compilation problem caused by non-English locale
38 #pragma setlocale("english")
41 RTest test(_L("T_Mount"));
43 static TInt gDriveNum=-1; ///< drive number we are dealing with
44 static TInt64 gRndSeed;
47 const TInt KBM_Repetitions = 5; ///< number of repetitions for BM testing
48 const TUint32 KCheckFileSize = 533; ///< size of the small file to be deleted
50 _LIT(KFileNameFirst, "\\FIRST%d.DAT");
51 _LIT(KFileNameMiddle, "\\MID%d.DAT");
52 _LIT(KFileNameLast, "\\LAST%d.DAT");
53 _LIT(KFileNameFiller, "\\FILL%d.DAT");
55 typedef void (*TStressFN)(TInt); //-- pointer to the FAT mount stress function
58 //-------------------------------------------------------------------
59 //-- debug bit flags that may be set in the property which controls FAT volume mounting
61 const TUid KThisTestSID={0x10210EB3}; ///< this EXE SID
63 const TUint32 KMntProp_EnableALL = 0x00000000; //-- enable all operations
67 const TUint32 KMntProp_DisableALL = 0xFFFFFFFF; //-- disable all operations
68 const TUint32 KMntProp_Disable_FsInfo = 0x00000001; //-- mask for disabling/enabling FSInfo information
69 const TUint32 KMntProp_Disable_FatBkGndScan = 0x00000002; //-- mask for disabling/enabling FAT background scanner
73 //-------------------------------------------------------------------
75 /** set a debug property value, which then wiil be read by FAT fsy */
76 void SetFsyDebugFlag(TInt aDriveNo, TUint32 aFlags)
80 nRes = RProperty::Set(KThisTestSID, aDriveNo, aFlags);
84 //-------------------------------------------------------------------
86 format the volume and read the boot sector
88 static void FormatVolume(TBool aQuickFormat)
93 //-- FAT32 SPC:1; for the FAT32 testing on the emulator
97 test.Printf(_L("This is emulator configuration!!!!\n"));
102 fp.iFatType = EFat32;
103 fp.iSecPerCluster = 1;
104 nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue, &fp); //-- always quick; doesn't matter for the emulator
106 nRes = FormatFatDrive(TheFs, CurrentDrive(), aQuickFormat);
113 //-------------------------------------------------------------------
116 Prepare FAT volume for mounting performance testing
118 1. quick format the drive
119 2. create KBM_Repetitions files in the beginning (first files)
120 3. create KMaxFillFiles/2 large files (they take about 40% of the volume);
121 4. create KBM_Repetitions files (middle files)
122 5. create KMaxFillFiles/2 large files (they take other 40% of the volume);
123 6. create KBM_Repetitions files (last files)
125 @return ETrue if everythis is OK
127 TBool PrepareVolumeForBM()
129 test.Printf(_L("Prepare the volume for BM testing...\n"));
134 //-- 1. quick format the drive
138 if(!Is_Fat32(TheFs, gDriveNum))
140 test.Printf(_L("This test requires FAT32 ! Skipping.\n"));
145 nRes = TheFs.Volume(volInfo, gDriveNum);
148 //-- the files will take 80% of the drive space
149 const TInt KMaxFillFiles = 100;
150 const TUint32 KFillFileSz = (TUint32)((volInfo.iFree*8) / (10*KMaxFillFiles));
152 //-- 2. create KBM_Repetitions files in the very begining (occupies first FAT entries)
155 for(i=0; i<KBM_Repetitions; ++i)
157 buf.Format(KFileNameFirst, i);
158 nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
162 //-- 3. Fill the FAT with entries and cteate a file in the middle
163 const TInt nHalf1 = KMaxFillFiles / 2;
165 for(i=0; i<nHalf1; ++i)
167 buf.Format(KFileNameFiller, i);
168 nRes = CreateEmptyFile(TheFs, buf, KFillFileSz);
172 //-- 4. create a files in the middle
173 for(i=0; i<KBM_Repetitions; ++i)
175 buf.Format(KFileNameMiddle, i);
176 nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
180 //-- 5. fill second half FAT
181 for(i=nHalf1; i<KMaxFillFiles; ++i)
183 buf.Format(KFileNameFiller, i);
184 nRes = CreateEmptyFile(TheFs, buf, KFillFileSz);
189 //-- 6. create files in the very end (occupiy last FAT entries)
190 for(i=0; i<KBM_Repetitions; ++i)
192 buf.Format(KFileNameLast, i);
193 nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize);
201 Mounts and dismounts FAT volume several times calculating average time taken to mount.
202 Also can stress FS by calling stress function that can do some work on the volume.
204 @param apStressFN pointer to the stressing function which can be called just after mounting. Can be NULL.
205 @return time in milliseconds taken to mout the volume
207 static TUint32 DoMeasureMountTime(TStressFN apStressFN)
215 TInt64 usMountTime=0; //-- total time taken by "Mount"
217 //-- disable FAT test utils print out, it can affects measured time
218 EnablePrintOutput(EFalse);
220 for(TInt i=0; i<KBM_Repetitions; ++i)
223 //-- A. remount FS taking the time when mounting starts
224 nRes = RemountFS(TheFs, gDriveNum, &timeStart);
227 //-- B. call a given stress function
231 //-- C. take end time
232 timeEnd.UniversalTime();
235 usMountTime += (timeEnd.MicroSecondsFrom(timeStart)).Int64();
238 const TUint32 msMountTime = (TUint32)usMountTime / (K1mSec*KBM_Repetitions);
240 EnablePrintOutput(ETrue); //-- Enable FAT test utils print out
245 //-------------------------------------------------------------------
249 Use case: read access to the first file on the volume in root dir.
251 static void FirstReadAccess_FirstFile_Stress(TInt aRepNo)
254 buf.Format(KFileNameFirst, aRepNo);
256 TInt nRes = VerifyCheckableFile(TheFs, buf);
263 Use case: read access to the middle file on the volume in root dir.
265 static void FirstReadAccess_MiddleFile_Stress(TInt aRepNo)
268 buf.Format(KFileNameMiddle, aRepNo);
270 TInt nRes = VerifyCheckableFile(TheFs, buf);
276 Use case: read access to the last file on the volume in root dir.
278 static void FirstReadAccess_LastFile_Stress(TInt aRepNo)
281 buf.Format(KFileNameLast, aRepNo);
283 TInt nRes = VerifyCheckableFile(TheFs, buf);
289 Use case: Getting volume information SYNCHRONOUSLY.
291 static void GetVolInfo_Synch_Stress(TInt)
294 TInt nRes = TheFs.Volume(volInfo, gDriveNum);
300 Use case: Getting volume information _ASYNCHRONOUSLY_, i.e. do not wait until
301 FAT32 free space scan thread finishes
303 static void GetVolInfo_Asynch_Stress(TInt)
307 //-- let's use special version of the RFS API
308 TRequestStatus rqStat;
309 TheFs.Volume(volInfo, gDriveNum, rqStat);
311 User::WaitForRequest(rqStat);
312 test(rqStat.Int()==KErrNone);
316 //-------------------------------------------------------------------
320 Use case: deletes files in the beginning of the volume (or FAT table)
322 static void DeleteFirstFile_Stress(TInt aRepNo)
325 buf.Format(KFileNameFirst, aRepNo);
327 TInt nRes = TheFs.Delete(buf);
334 Use case: deletes files in the middle of the volume (or FAT table)
336 static void DeleteMiddleFile_Stress(TInt aRepNo)
339 buf.Format(KFileNameMiddle, aRepNo);
341 TInt nRes = TheFs.Delete(buf);
347 Use case: deletes files in the end of the volume (or FAT table)
349 static void DeleteLastFile_Stress(TInt aRepNo)
352 buf.Format(KFileNameLast, aRepNo);
354 TInt nRes = TheFs.Delete(buf);
359 //-------------------------------------------------------------------
362 perform series of tests that measure and print out FAT volume mount time for different secenarios
364 void MeasureMountTime()
368 if(!PrepareVolumeForBM()) //-- prepare the volume for BM tests: format it, create file structure etc.
371 //-- 1. no stress function, measure just pure mount time
372 msTime = DoMeasureMountTime(NULL);
373 test.Printf(_L("#--> Pure mount:%d ms\n"), msTime);
375 //-- 2.1 measure mount time with a read-acess to the first file on the volume
376 msTime = DoMeasureMountTime(FirstReadAccess_FirstFile_Stress);
377 test.Printf(_L("#--> mount and read access to 1st file:%d ms\n"), msTime);
379 //-- 2.2 measure mount time with a read-acess to the middle file on the volume
380 msTime = DoMeasureMountTime(FirstReadAccess_MiddleFile_Stress);
381 test.Printf(_L("#--> mount and read access to middle file:%d ms\n"), msTime);
383 //-- 2.3 measure mount time with a read-acess to the last file on the volume
384 msTime = DoMeasureMountTime(FirstReadAccess_LastFile_Stress);
385 test.Printf(_L("#--> mount and read access to last file:%d ms\n"), msTime);
387 //-- 2.4 measure mount time with getting a volume information
388 msTime = DoMeasureMountTime(GetVolInfo_Synch_Stress);
389 test.Printf(_L("#--> mount and getting volInfo (synch):%d ms\n"), msTime);
391 msTime = DoMeasureMountTime(GetVolInfo_Asynch_Stress);
392 test.Printf(_L("#--> mount and getting volInfo (Asynch):%d ms\n"), msTime);
395 //-- 2.4 measure mount time with deleting file in the beginning (write access to the first entries of the FAT32)
396 msTime = DoMeasureMountTime(DeleteFirstFile_Stress);
397 test.Printf(_L("#--> mount and delete first file:%d ms\n"), msTime);
399 //-- 2.5 measure mount time with deleting file in the middle (write access to the middle entries of the FAT32)
400 msTime = DoMeasureMountTime(DeleteMiddleFile_Stress);
401 test.Printf(_L("#--> mount and delete middle file:%d ms\n"), msTime);
403 //-- 2.6 measure mount time with deleting file in the end (write access to the last entries of the FAT32)
404 msTime = DoMeasureMountTime(DeleteLastFile_Stress);
405 test.Printf(_L("#--> mount and delete last file:%d ms\n"), msTime);
407 test.Printf(_L("---\n"), msTime);
410 //----------------------------------------------------------------------------------------------
411 //! @SYMTestCaseID PBASE-T_MOUNT-0521
413 //! @SYMPREQ PREQ1721
414 //! @SYMTestCaseDesc Testing FAT volume mount performance for various scenarios
417 //! 0 Prepare the volume by formatting it and creating 100 files to occupy the space.
418 //! 1 Turn OFF all mount enhancements
419 //! 2 Measure and print out volume mount time for the next scenarios:
421 //! b. mount and read access to the media (reading the last file in the root dir.)
422 //! c. mount and write access to the media (writing data into the last file in the root dir)
423 //! d. mount getting volume information
426 //! 3 Turn ON using FSInfo.
427 //! 4 Repeat step 2 for this case.
428 //! @SYMTestExpectedResults Finishes ok.
429 //! @SYMTestPriority High
430 //! @SYMTestStatus Implemented
431 //----------------------------------------------------------------------------------------------
432 void TestFAT_Mounting_Performance()
434 test.Next(_L("\n#--> Measuring FAT volumes mount performance.\n"));
436 test.Printf(_L("Skipping the test in the Release build! \n"));
440 //-- 1. turn OFF all mount enhancements like using FSInfo, backround FAT scan etc.
441 test.Printf(_L("#--> ==== All mount enhancements are disabled ====\n"));
442 SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL);
445 //-- 2. Turn ON using FSInfo
446 test.Printf(_L("#--> ==== Enabled Using FSInfo ====\n"));
447 SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FsInfo);
450 //-- 2. Turn OFF using FSInfo and ON FAT32 bacground scanning
451 test.Printf(_L("#--> ==== Enabled FAT32 BkGnd scan, FSInfo disabled ====\n"));
452 SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FatBkGndScan);
455 //-- restore mounting mechanism
456 SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
463 //-------------------------------------------------------------------
466 Check if the drive aDriveNo is finalised or not.
467 The "CleanShutDown" is obtained by QueryVolumeInfoExt API and by reading 2 FATs directly with checking their consistence.
469 @param aDriveNo drive number to query.
470 @return ETrue if the drive if finalised
472 static TBool DoCheckVolumeFinalised(TInt aDriveNo)
475 TPckgBuf<TBool> boolPckg;
477 //-- 1. get "Finalised" state by using the API
478 nRes = TheFs.QueryVolumeInfoExt(aDriveNo, EIsDriveFinalised, boolPckg);
481 //-- N.B. for FAT12 the result can be either OK or "NotSupported"
482 //-- If FAT12 is in explicit "finalised" state, the result will be OK
483 //-- if not, we can't query the volume state, because FAT12 doesn't support flags in FAT[1]
485 const TBool bFinalised_From_API = boolPckg() >0;
486 TBool bFinalised_From_FAT1 = bFinalised_From_API;
488 TBuf8<32> fatBuf(32);
489 TFatBootSector bootSec;
490 const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
492 nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, bootSec);
495 test(bootSec.IsValid());
497 const TUint32 Fat1StartPos = bootSec.FirstFatSector() * bootSec.BytesPerSector();
499 if(bootSec.FatType() == EFat16)
502 const TUint16 KClnShtdnMask = 0x8000; //-- "ClnShutBitMask", see FAT specs
504 //-- read "CleanShutDown" flag directly from the 1st FAT
505 nRes = MediaRawRead(TheFs, gDriveNum, Fat1StartPos, fatBuf.Size(), fatBuf);
508 Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
509 bFinalised_From_FAT1 = (fatEntry & KClnShtdnMask) >0;
512 for(TInt i=1; i<bootSec.NumberOfFats(); ++i)
514 //-- read a flag from the next FAT
515 const TUint32 currFatStartPos = (bootSec.FirstFatSector() + i*bootSec.TotalFatSectors())*bootSec.BytesPerSector();
517 nRes = MediaRawRead(TheFs, gDriveNum, currFatStartPos, fatBuf.Size(), fatBuf);
520 Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
521 const TBool bFinalised_From_currFAT = (fatEntry & KClnShtdnMask)>0;
523 test(bFinalised_From_currFAT == bFinalised_From_FAT1);
527 else if(bootSec.FatType() == EFat32)
530 const TUint32 KClnShtdnMask = 0x08000000; //-- "ClnShutBitMask", see FAT specs
532 //-- read "CleanShutDown" flag directly from the 1st FAT
533 nRes = MediaRawRead(TheFs, gDriveNum, Fat1StartPos, fatBuf.Size(), fatBuf);
536 Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
537 bFinalised_From_FAT1 = (fatEntry & KClnShtdnMask) >0;
539 for(TInt i=1; i<bootSec.NumberOfFats(); ++i)
541 //-- read a flag from the next FAT
542 const TUint32 currFatStartPos = (bootSec.FirstFatSector() + i*bootSec.TotalFatSectors())*bootSec.BytesPerSector();
544 nRes = MediaRawRead(TheFs, gDriveNum, currFatStartPos, fatBuf.Size(), fatBuf);
547 Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry));
548 const TBool bFinalised_From_currFAT = (fatEntry & KClnShtdnMask) >0;
550 test(bFinalised_From_currFAT == bFinalised_From_FAT1);
555 {//-- FAT12 doesn't have flags in FAT[1]
556 bFinalised_From_FAT1 = bFinalised_From_API;
559 test(bFinalised_From_FAT1 == bFinalised_From_API);
561 return bFinalised_From_API;
566 //----------------------------------------------------------------------------------------------
567 //! @SYMTestCaseID PBASE-T_MOUNT-0522
569 //! @SYMPREQ PREQ1721
570 //! @SYMTestCaseDesc RFs::FinaliseDrive() and RFs::FinaliseDrives() API
573 //! 0 Finalise the drive in RW mode and check the result.
574 //! 1 Finalise the drive in RW mode once again and check the result.
575 //! 2 Create a file and check that the volume has become unfinalised.
576 //! 3 Open a file, try to finalise the volume; it shall fail with KErrInUse
577 //! 4 close the file, finalise, check that the result is OK.
578 //! 5 "Unfinalise" the volume; check that the volume is not finalised any longer.
579 //! 6 Finalise the drive in RO mode and check the result.
580 //! 7 Try to create a file, shall fail with KErrAccessDenied
581 //! 8 Try to finalise into RW mode, shall fail with KErrAccessDenied
582 //! 9 Try to unfinalise volume, it shall remain RO
583 //! 10 Remount the drive, it shall become RW and finalised
584 //! 11 Test transition "Not finalised" -> EFinal_RW (expected: KErrNone)
585 //! 12 Test transition EFinal_RW -> EFinal_RO (expected: KErrNone)
586 //! 13 Test transition EFinal_RO -> EFinal_RW (expected: KErrAccessDenied)
587 //! 14 Remount the volume to reset RO flag
588 //! 15 test old RFs::FinaliseDrives() API by finalising all drives in the system
590 //! @SYMTestExpectedResults finishes if the volume finalisation works correctly. panics otherwise
591 //! @SYMTestPriority High
592 //! @SYMTestStatus Implemented
593 //----------------------------------------------------------------------------------------------
594 static void TestFinaliseFS()
596 test.Next(_L("Testing RFs::FinaliseDrives() API\n"));
598 if(!Is_Fat16(TheFs, gDriveNum) && !Is_Fat32(TheFs, gDriveNum))
600 test.Printf(_L("This step requires FAT16 or FAT32 ! Skipping.\n"));
605 TBool bDriveFinalised;
607 //============= 1. finalise the drive (RW mode) and check the result
608 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
611 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
612 test(bDriveFinalised);
614 //-- 1.1 finalise the drive second time EFinal_RW -> EFinal_RW shall work
615 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
618 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
619 test(bDriveFinalised);
621 //============= 2. create a file. Shall succeed (EFinal_RW), the volume shall become unfinalised
624 _LIT(KFileName, "\\my_file1.dat");
626 nRes = CreateEmptyFile(TheFs, KFileName, 128000);
629 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
630 test(!bDriveFinalised); //-- the volume has become "unfinalised"
632 //-- 2.1 open a file, try to finalise; Shall dail with KErrInUse
633 nRes = file.Replace(TheFs, KFileName, EFileWrite | EFileRead);
636 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
637 test(nRes==KErrInUse); //-- can't finalise drives with opened objects
641 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
644 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
645 test(bDriveFinalised);
647 //============= 3. test "unfinalise API"
648 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EForceUnfinalise);
651 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
652 test(!bDriveFinalised); //-- the volume has become "unfinalised"
654 //============= 4. test finalisation into RO mode
655 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RO); //-- the volume becomes RO
658 //-- try to write a file on RO volume; it shall fail with KErrAccessDenied
659 nRes = CreateEmptyFile(TheFs, KFileName, 128000);
660 test(nRes == KErrAccessDenied);
663 //-- 4.1 try to finalise into EFinal_RW mode, shall fail with KErrAccessDenied
664 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
665 test(nRes == KErrAccessDenied);
667 //-- 4.2 "unfinalise" the volume, it still shall remain RO
668 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EForceUnfinalise);
671 //-- try to write a file on RO volume; it shall fail with KErrAccessDenied
672 nRes = CreateEmptyFile(TheFs, KFileName, 128000);
673 test(nRes == KErrAccessDenied);
676 //-- remount FS, the drive shall become RW
677 nRes = RemountFS(TheFs, gDriveNum);
680 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
681 test(bDriveFinalised);
683 //-- try to write a file on RW volume, shall be OK
684 nRes = CreateEmptyFile(TheFs, KFileName, 128000);
685 test(nRes == KErrNone);
688 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
689 test(!bDriveFinalised);
691 //============= 5. test various finalisation modes
693 //-- 5.1 Not finalised -> EFinal_RW (KErrNone)
694 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
695 test(nRes == KErrNone);
696 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
697 test(bDriveFinalised);
699 //-- 5.2 EFinal_RW -> EFinal_RO (KErrNone)
700 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RO);
701 test(nRes == KErrNone);
702 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
703 test(bDriveFinalised);
705 //-- 5.2 EFinal_RO -> EFinal_RW (KErrAccessDenied)
706 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
707 test(nRes == KErrAccessDenied);
708 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
709 test(bDriveFinalised);
712 nRes = RemountFS(TheFs, gDriveNum);
716 //============= 6. test old RFs::FinaliseDrives API
718 nRes = CreateEmptyFile(TheFs, KFileName, 128000);
719 test(nRes == KErrNone);
721 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
722 test(!bDriveFinalised);
724 TheFs.FinaliseDrives(); //-- shall work as TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW) but for ALL drives
726 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
727 test(bDriveFinalised);
729 nRes = CreateEmptyFile(TheFs, KFileName, 128000);
730 test(nRes == KErrNone);
734 //----------------------------------------------------------------------------------------------
735 //! @SYMTestCaseID PBASE-T_MOUNT-0523
737 //! @SYMPREQ PREQ1721
738 //! @SYMTestCaseDesc testing boot and backup boot sectors on FAT32 volume
741 //! 0 Quick format the drive
742 //! 1 read main and backup boot & fsinfo sectors and check their validity
743 //! 2 corrupt main boot sector and check that the drive can be mounted (backup boot sector is used)
744 //! 3 corrupt backup boot sector and check that the drive can not be mounted.
745 //! 4 Quick format the drive to restore test environment
747 //! @SYMTestExpectedResults finishes if the boot sector and backup boot sector functionality compliant with the FAT specs. panics otherwise
748 //! @SYMTestPriority High
749 //! @SYMTestStatus Implemented
750 //----------------------------------------------------------------------------------------------
751 static void TestBackupBootSector()
753 test.Next(_L("Testing Backup Boot Sector.\n"));
757 //-- quick format the drive
760 if(!Is_Fat32(TheFs, gDriveNum))
762 test.Printf(_L("This step requires FAT32 ! Skipping.\n"));
766 TFatBootSector mainBootSec, backupBootSec;
767 TFSInfo mainFSInfo, backupFSInfo;
769 const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
770 const TUint32 posBkBootSec = KBkBootSectorNum << KDefaultSectorLog2;
772 //-- read main and backup boot & fsinfo sectors and check their validity
773 nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, mainBootSec);
776 //-- backup boot sector # must be 6
777 nRes = ReadBootSector(TheFs, gDriveNum, posBkBootSec, backupBootSec);
780 test(mainBootSec.IsValid());
781 test(backupBootSec.IsValid());
782 test(mainBootSec == backupBootSec);
784 //-- read fsinfo sectors
785 const TUint32 posMainFSInfo = mainBootSec.FSInfoSectorNum() << KDefaultSectorLog2;
786 const TUint32 posBkFSInfo = (KBkBootSectorNum + mainBootSec.FSInfoSectorNum()) << KDefaultSectorLog2;
788 test(posMainFSInfo != 0);
789 test(posBkFSInfo != 0);
791 nRes = ReadFSInfoSector(TheFs, gDriveNum, posMainFSInfo, mainFSInfo);
794 nRes = ReadFSInfoSector(TheFs, gDriveNum, posBkFSInfo, backupFSInfo);
797 test(mainFSInfo.IsValid());
798 test(backupFSInfo.IsValid());
799 test(mainFSInfo == backupFSInfo);
801 //-- corrupt main boot sector and check that the drive can be mounted
802 test.Printf(_L("Corrupting main boot sector...\n"));
805 //-- A1. corrupt main boot sector starting from the pos:0
806 nRes = FillMedia(TheFs, gDriveNum, posMainBootSec, posMainBootSec+KDefaultSectorSize, 0xaa);
808 //-- A2. remount FS, it shall be OK because of the using backup boot sector
809 nRes = RemountFS(TheFs, gDriveNum);
813 //-- B1. corrupt BACKUP boot sector starting from the sec:6
814 nRes = FillMedia(TheFs, gDriveNum, posBkBootSec, posBkBootSec+KDefaultSectorSize, 0xbb);
816 //-- B2. remount FS, unable to mount.
817 nRes = RemountFS(TheFs, gDriveNum);
818 test(nRes == KErrCorrupt);
821 //-- quick format the drive
826 //----------------------------------------------------------------------------------------------
827 //! @SYMTestCaseID PBASE-T_MOUNT-0524
829 //! @SYMPREQ PREQ1721
830 //! @SYMTestCaseDesc testing FSInfo sector functionality.
833 //! 0 Quick format the drive
834 //! 1 finalise the drive to write correct data to the FSInfo & its backup copy.
835 //! 2 read FSInfo sector, its backup copy and check that they are both valid, identical and contain correct data
836 //! 3 check that after the formatting FS info values are the same as real, obtained from the FAT scanning.
837 //! 4 create a random - sized file, check that after finalisation the number of free clusters is identical to the FSinfo
838 //! 5 Quick format the drive to restore test environment
840 //! @SYMTestExpectedResults finishes if the FSInfo sectors functionality compliant with the FAT specs. panics otherwise
841 //! @SYMTestPriority High
842 //! @SYMTestStatus Implemented
843 //----------------------------------------------------------------------------------------------
844 static void TestFSInfoSector()
846 test.Next(_L("Testing FSInfo Sector.\n"));
849 test.Printf(_L("Skipping the test in the Release build! \n"));
855 //-- quick format the drive
858 if(!Is_Fat32(TheFs, gDriveNum))
860 test.Printf(_L("This step requires FAT32 ! Skipping.\n"));
864 TFatBootSector bootSec;
865 const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2;
866 nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, bootSec);
869 const TUint32 bytesPerSector = bootSec.BytesPerSector();
870 const TUint32 secPerClust = bootSec.SectorsPerCluster();
872 //-- finalise the drive, just in case
873 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
876 //============= 1. read FSInfo sector and its backup copy and compare them
880 nRes = ReadFSInfoSector(TheFs, gDriveNum, KFSInfoSectorNum*bytesPerSector, fsInfoSec);
882 test(fsInfoSec.IsValid());
884 TUint32 freeClusters_FSInfo = fsInfoSec.FreeClusterCount();
885 TUint32 nextFree_FSInfo = fsInfoSec.NextFreeCluster();
888 nRes = ReadFSInfoSector(TheFs, gDriveNum, KBkFSInfoSectorNum*bytesPerSector, fsInfoSec);
890 test(fsInfoSec.IsValid());
892 //-- both copies must be identical
893 test(freeClusters_FSInfo == fsInfoSec.FreeClusterCount());
894 test(nextFree_FSInfo == fsInfoSec.NextFreeCluster());
896 //-- FAT[0] and FAT[1] are not used; FAT[2] is taken by the 1st cluster of the FAT32 Root directory.
897 test(nextFree_FSInfo == (2+1));
899 //============= 2. check that after the formatting FS info values are the same as real.
901 //-- 2.1 disable using FSInfo and other stuff
902 SetFsyDebugFlag(gDriveNum, KMntProp_Disable_FsInfo);
904 //-- remount FAT; using FSInfo is disabled. FAT will be explicitly scanned.
905 nRes = RemountFS(TheFs, gDriveNum);
908 //-- restore mounting mechanism
909 SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
911 //-- get free clusters number from the FSY, which in turn had counted them explicitly
913 nRes = TheFs.Volume(volInfo, gDriveNum);
916 TUint32 freeClusters = (TUint32)(volInfo.iFree / (bytesPerSector * secPerClust));
917 test(freeClusters == freeClusters_FSInfo);
919 //============= 3. create a random - sized file, check that after finalisation the number of free clusters is identical to the FSinfo
920 _LIT(KFileName, "\\FILE1.DAT");
921 const TUint32 rndClusters = 7+((TUint32)Math::Rand(gRndSeed)) % 5000;
922 const TUint32 fileSz = rndClusters * bytesPerSector * secPerClust;
923 nRes = CreateEmptyFile(TheFs, KFileName, fileSz);
926 //-- 3.1 get data from FS
927 nRes = TheFs.Volume(volInfo, gDriveNum);
929 freeClusters = (TUint32)(volInfo.iFree / (bytesPerSector * secPerClust));
931 //-- 3.2 finalise the volume and get data from FSInfo
932 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW);
936 nRes = ReadFSInfoSector(TheFs, gDriveNum, KFSInfoSectorNum*bytesPerSector, fsInfoSec);
938 test(fsInfoSec.IsValid());
940 freeClusters_FSInfo = fsInfoSec.FreeClusterCount();
941 nextFree_FSInfo = fsInfoSec.NextFreeCluster();
944 nRes = ReadFSInfoSector(TheFs, gDriveNum, KBkFSInfoSectorNum*bytesPerSector, fsInfoSec);
946 test(fsInfoSec.IsValid());
948 //-- both copies must be identical
949 test(freeClusters_FSInfo == fsInfoSec.FreeClusterCount());
950 test(nextFree_FSInfo == fsInfoSec.NextFreeCluster());
952 //-- the information in FSInfo must be the same as in FAT
953 test(freeClusters == freeClusters_FSInfo);
955 TBool bDriveFinalised = DoCheckVolumeFinalised(gDriveNum);
956 test(bDriveFinalised);
958 TheFs.Delete(KFileName);
960 //-- restore mounting mechanism
961 SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
966 //-------------------------------------------------------------------
968 /** initialise test global objects */
969 static void InitGlobals()
973 //-- define a propery which will control mount process in the fsy.
974 //-- The property key is a drive number being tested
976 _LIT_SECURITY_POLICY_PASS(KTestPropPolicy);
977 nRes = RProperty::Define(KThisTestSID, gDriveNum, RProperty::EInt, KTestPropPolicy, KTestPropPolicy);
978 test(nRes == KErrNone || nRes == KErrAlreadyExists);
980 nRes = RProperty::Set(KThisTestSID, gDriveNum, KMntProp_EnableALL);
983 gRndSeed = Math::Random();
984 (void)&gRndSeed; //-- get rid of warning
987 /** destroy test global objects */
988 static void DestroyGlobals()
990 //-- delete test property
991 RProperty::Delete(KThisTestSID, gDriveNum);
997 //-------------------------------------------------------------------
999 Manual test. Requires manual removing and putting back the media.
1000 On the emulator one can use pressing (and holding) F5 key to simulate media removal.
1002 void Manual_TestRemount_On_MediaRemoval()
1006 _LIT(KFileName, "\\my_file1.dat");
1007 const TUint32 KFileSz = K1MegaByte;
1009 //-- 1. create a file
1010 nRes = CreateEmptyFile(TheFs, KFileName, KFileSz);
1011 test_KErrNone(nRes);
1015 nRes = file.Open(TheFs, KFileName, EFileRead | EFileWrite);
1016 test_KErrNone(nRes);
1018 TBuf8<512> buf(512);
1026 TheFs.SetDebugRegister(0x00);
1028 nRes = file.Read(0, buf);
1030 test.Printf(_L("Remove the media and press a key.\n"));
1032 if(key == EKeyEscape)
1035 TheFs.SetDebugRegister(KFSYS | KFSERV);
1036 nRes = file.Read(0, buf);
1038 if(nRes != KErrNone)
1041 test.Printf(_L("ReadFile: %d!\n"), nRes);
1044 if(key == EKeyEscape)
1047 nRes = TheFs.Volume(vi,gDriveNum);
1048 test.Printf(_L("Volume: %d!\n"), nRes);
1051 if(key == EKeyEscape)
1054 nRes = file.Write(0, buf);
1055 test.Printf(_L("WriteFile: %d!\n"), nRes);
1058 if(key == EKeyEscape)
1070 //-------------------------------------------------------------------
1072 Wait for the request aRqStat to be completed with timeout.
1074 @param aRqStat request status object we need to wait to complete
1075 @param aTimeout_uS timeout in microseconds
1077 @return ETrue if the aRqStat is completed before time is out
1078 EFalse if aTimeout_uS has passed. And the state of the aRqStat not changed.
1080 TBool WaitForRequestWithTimeout(TRequestStatus& aRqStat, TUint32 aTimeout_uS)
1082 TRequestStatus rqStatTimeout(KRequestPending);
1085 TBool bReqCompleted;
1087 if(aRqStat.Int() != KRequestPending)
1088 return ETrue; //-- nothing to wait for.
1090 //-- set up a timeout timer
1091 nRes = tmrTimeOut.CreateLocal();
1092 test(nRes == KErrNone);
1094 tmrTimeOut.After(rqStatTimeout, aTimeout_uS);
1096 User::WaitForRequest(aRqStat, rqStatTimeout);
1098 if(aRqStat == KRequestPending)
1100 bReqCompleted = EFalse;
1103 {//-- the main request has been completed, cancel timer
1104 bReqCompleted = ETrue;
1105 if(rqStatTimeout.Int() == KRequestPending)
1107 tmrTimeOut.Cancel();
1108 User::WaitForRequest(rqStatTimeout);
1114 return bReqCompleted;
1117 //-------------------------------------------------------------------
1119 void TestNotifyDiskSpace()
1121 test.Next(_L("Testing NotifyDiskSpace() on asynchronous mounting\n"));
1124 test.Printf(_L("Skipping the test in the Release build! \n"));
1129 TRequestStatus rqStat;
1130 TVolumeInfo volInfo;
1132 //-- quick format the drive
1133 FormatVolume(ETrue);
1135 if(!Is_Fat32(TheFs, gDriveNum))
1136 {//-- only FAT32 supports asynch mounting;
1137 test.Printf(_L("This test step requires FAT32!\n"));
1141 //-- FAT32 free space threshold that is supposed to be triggered by notifiers
1142 const TInt64 KFreeSpaceThreshold = 300*K1MegaByte;
1144 //-- Turn OFF using FSInfo and ON FAT32 background scanning; it will cause compulsory FAT32 background free clusters scan.
1145 //-- if FAT32 background free clusters scan is disabled in config, this test can hang on waiting for free space notifications.
1146 test.Printf(_L("==== Enabled FAT32 BkGnd scan, FSInfo disabled ====\n"));
1147 SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FatBkGndScan);
1150 //===== create a big file in the beginning in order to avoid freeSpaceThreshold being reached too fast
1151 nRes = CreateEmptyFile(TheFs, _L("\\big_empty_file.bin"), 10*K1MegaByte);
1152 test_KErrNone(nRes);
1154 //TheFs.SetDebugRegister(0x03);
1156 //===== Test that FAT32 free space scanning thread updates File Server free space notifiers
1157 test.Printf(_L("Testing FAT32 free space scanning thread triggers notifiers..."));
1159 nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it must cause FAT32 free space scan in background
1160 test_KErrNone(nRes);
1162 test.Printf(_L("Waiting for %LU bytes available on the volume...\n"), KFreeSpaceThreshold);
1164 //-- check if we can use the notifiers at all... If free space is >= KFreeSpaceThreshold, the notifier won't be triggered
1165 //-- get _current_ amount of free space asynchronously
1166 TheFs.Volume(volInfo, gDriveNum, rqStat);
1167 User::WaitForRequest(rqStat);
1168 test(rqStat.Int()==KErrNone);
1170 if(volInfo.iSize <= KFreeSpaceThreshold)
1172 test.Printf(_L("The volume is too small for %LU bytes notify ...\n"), KFreeSpaceThreshold);
1173 test.Printf(_L("The test is inconclusive ...\n"));
1177 if(volInfo.iFree >= KFreeSpaceThreshold)
1179 test.Printf(_L("The volume already has %LU free bytes...\n"), volInfo.iFree);
1180 test.Printf(_L("The test is inconclusive ...\n"));
1185 TheFs.NotifyDiskSpace(KFreeSpaceThreshold, gDriveNum, rqStat);
1186 test(rqStat.Int()==KRequestPending);
1188 //-- wait for notification for 30 seconds; If for some reason FAT32 background scanning for free clusters doesn't
1189 //-- work (e.g. configued out in FAT), this test is inconclusive.
1190 TBool bCompleted = WaitForRequestWithTimeout(rqStat, 30*K1Sec);
1194 test.Printf(_L("Wait timeout! something is wrong...\n"));
1198 test_KErrNone(rqStat.Int());
1200 //-- get _current_ amount of free space asynchronously
1201 TheFs.Volume(volInfo, gDriveNum, rqStat);
1202 User::WaitForRequest(rqStat);
1203 test(rqStat.Int()==KErrNone);
1204 test.Printf(_L("Current amount of free space on the volume: %LU \n"), volInfo.iFree);
1207 //===== Test that aborting FAT32 free space scanning thread will trigger notifiers
1208 test.Printf(_L("Testing aborting FAT32 free space scanning thread..."));
1210 nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it must cause FAT32 free space scan in background
1211 test_KErrNone(nRes);
1213 TheFs.NotifyDiskSpace(KFreeSpaceThreshold, gDriveNum, rqStat);
1214 test(rqStat.Int()==KRequestPending);
1216 nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it will abort the scanning thread
1217 test_KErrNone(nRes);
1219 test(rqStat.Int() != KRequestPending);
1221 //-- get _current_ amount of free space asynchronously
1222 TheFs.Volume(volInfo, gDriveNum, rqStat);
1223 User::WaitForRequest(rqStat);
1224 test(rqStat.Int()==KErrNone);
1225 test.Printf(_L("Current amount of free space on the volume: %LU \n"), volInfo.iFree);
1228 //-- find out free space on the volume; it will also blocks until FAT32 free space scanning finishes.
1229 nRes = TheFs.Volume(volInfo);
1230 test(nRes==KErrNone);
1231 test.Printf(_L("free space on the volume: %LU \n"), volInfo.iFree);
1234 //TheFs.SetDebugRegister(0x00);
1236 //-- restore mounting mechanism
1237 SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL);
1242 //-------------------------------------------------------------------
1246 //-- set up console output
1247 Fat_Test_Utils::SetConsole(test.Console());
1249 TInt nRes=TheFs.CharToDrive(gDriveToTest, gDriveNum);
1250 test(nRes==KErrNone);
1252 //-- check if this is FAT
1253 if(!Is_Fat(TheFs, gDriveNum) || Is_Automounter(TheFs, gDriveNum))
1254 {//-- it doesn't make much sense to run this test under automounter+FAT. The automounter can't easily handle formatting corrupted media
1255 //-- and the mounting permaormance measurements don't make much sense in this case as well.
1257 test.Printf(_L("Skipping. This test requires explicitly mounted FAT file system.\n"));
1261 //-- check this is not the internal ram drive
1264 nRes = TheFs.Volume(v);
1265 test(nRes==KErrNone);
1266 if(v.iDrive.iMediaAtt & KMediaAttVariableSize)
1268 test.Printf(_L("Skipping. Internal ram drive not tested.\n"));
1272 //-------------------------------------
1274 PrintDrvInfo(TheFs, gDriveNum);
1278 TestNotifyDiskSpace();
1280 //-------------------------------------
1281 TestBackupBootSector();
1285 //-------------------------------------
1286 TestFAT_Mounting_Performance();
1287 //-------------------------------------
1289 //Manual_TestRemount_On_MediaRemoval();
1291 //-------------------------------------