|
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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // f32test\server\t_mount.cpp |
|
15 // Testing some issues connected with mounting/dismounting file fystems, drives finalisation etc. |
|
16 // |
|
17 // |
|
18 |
|
19 /** |
|
20 @file |
|
21 */ |
|
22 |
|
23 #define __E32TEST_EXTENSION__ |
|
24 |
|
25 #include <f32file.h> |
|
26 #include <e32test.h> |
|
27 #include <e32math.h> |
|
28 #include <e32property.h> |
|
29 #include <f32dbg.h> |
|
30 |
|
31 #include "t_server.h" |
|
32 #include "fat_utils.h" |
|
33 |
|
34 using namespace Fat_Test_Utils; |
|
35 |
|
36 #ifdef __VC32__ |
|
37 // Solve compilation problem caused by non-English locale |
|
38 #pragma setlocale("english") |
|
39 #endif |
|
40 |
|
41 RTest test(_L("T_Mount")); |
|
42 |
|
43 static TInt gDriveNum=-1; ///< drive number we are dealing with |
|
44 static TInt64 gRndSeed; |
|
45 |
|
46 |
|
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 |
|
49 |
|
50 _LIT(KFileNameFirst, "\\FIRST%d.DAT"); |
|
51 _LIT(KFileNameMiddle, "\\MID%d.DAT"); |
|
52 _LIT(KFileNameLast, "\\LAST%d.DAT"); |
|
53 _LIT(KFileNameFiller, "\\FILL%d.DAT"); |
|
54 |
|
55 typedef void (*TStressFN)(TInt); //-- pointer to the FAT mount stress function |
|
56 |
|
57 |
|
58 //------------------------------------------------------------------- |
|
59 //-- debug bit flags that may be set in the property which controls FAT volume mounting |
|
60 |
|
61 const TUid KThisTestSID={0x10210EB3}; ///< this EXE SID |
|
62 |
|
63 const TUint32 KMntProp_EnableALL = 0x00000000; //-- enable all operations |
|
64 |
|
65 #ifdef _DEBUG |
|
66 |
|
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 |
|
70 |
|
71 #endif |
|
72 |
|
73 //------------------------------------------------------------------- |
|
74 |
|
75 /** set a debug property value, which then wiil be read by FAT fsy */ |
|
76 void SetFsyDebugFlag(TInt aDriveNo, TUint32 aFlags) |
|
77 { |
|
78 TInt nRes; |
|
79 |
|
80 nRes = RProperty::Set(KThisTestSID, aDriveNo, aFlags); |
|
81 test_KErrNone(nRes); |
|
82 } |
|
83 |
|
84 //------------------------------------------------------------------- |
|
85 /** |
|
86 format the volume and read the boot sector |
|
87 */ |
|
88 static void FormatVolume(TBool aQuickFormat) |
|
89 { |
|
90 TInt nRes; |
|
91 |
|
92 #if 0 |
|
93 //-- FAT32 SPC:1; for the FAT32 testing on the emulator |
|
94 (void)aQuickFormat; |
|
95 |
|
96 #ifdef __EPOC32__ |
|
97 test.Printf(_L("This is emulator configuration!!!!\n")); |
|
98 test(0); |
|
99 #endif |
|
100 |
|
101 TFatFormatParam fp; |
|
102 fp.iFatType = EFat32; |
|
103 fp.iSecPerCluster = 1; |
|
104 nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue, &fp); //-- always quick; doesn't matter for the emulator |
|
105 #else |
|
106 nRes = FormatFatDrive(TheFs, CurrentDrive(), aQuickFormat); |
|
107 #endif |
|
108 |
|
109 test_KErrNone(nRes); |
|
110 |
|
111 } |
|
112 |
|
113 //------------------------------------------------------------------- |
|
114 |
|
115 /** |
|
116 Prepare FAT volume for mounting performance testing |
|
117 |
|
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) |
|
124 |
|
125 @return ETrue if everythis is OK |
|
126 */ |
|
127 TBool PrepareVolumeForBM() |
|
128 { |
|
129 test.Printf(_L("Prepare the volume for BM testing...\n")); |
|
130 |
|
131 TInt nRes; |
|
132 TInt i; |
|
133 |
|
134 //-- 1. quick format the drive |
|
135 FormatVolume(ETrue); |
|
136 |
|
137 |
|
138 if(!Is_Fat32(TheFs, gDriveNum)) |
|
139 { |
|
140 test.Printf(_L("This test requires FAT32 ! Skipping.\n")); |
|
141 return EFalse; |
|
142 } |
|
143 |
|
144 TVolumeInfo volInfo; |
|
145 nRes = TheFs.Volume(volInfo, gDriveNum); |
|
146 test_KErrNone(nRes); |
|
147 |
|
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)); |
|
151 |
|
152 //-- 2. create KBM_Repetitions files in the very begining (occupies first FAT entries) |
|
153 TBuf<64> buf; |
|
154 |
|
155 for(i=0; i<KBM_Repetitions; ++i) |
|
156 { |
|
157 buf.Format(KFileNameFirst, i); |
|
158 nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize); |
|
159 test_KErrNone(nRes); |
|
160 } |
|
161 |
|
162 //-- 3. Fill the FAT with entries and cteate a file in the middle |
|
163 const TInt nHalf1 = KMaxFillFiles / 2; |
|
164 |
|
165 for(i=0; i<nHalf1; ++i) |
|
166 { |
|
167 buf.Format(KFileNameFiller, i); |
|
168 nRes = CreateEmptyFile(TheFs, buf, KFillFileSz); |
|
169 test_KErrNone(nRes); |
|
170 } |
|
171 |
|
172 //-- 4. create a files in the middle |
|
173 for(i=0; i<KBM_Repetitions; ++i) |
|
174 { |
|
175 buf.Format(KFileNameMiddle, i); |
|
176 nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize); |
|
177 test_KErrNone(nRes); |
|
178 } |
|
179 |
|
180 //-- 5. fill second half FAT |
|
181 for(i=nHalf1; i<KMaxFillFiles; ++i) |
|
182 { |
|
183 buf.Format(KFileNameFiller, i); |
|
184 nRes = CreateEmptyFile(TheFs, buf, KFillFileSz); |
|
185 test_KErrNone(nRes); |
|
186 } |
|
187 |
|
188 |
|
189 //-- 6. create files in the very end (occupiy last FAT entries) |
|
190 for(i=0; i<KBM_Repetitions; ++i) |
|
191 { |
|
192 buf.Format(KFileNameLast, i); |
|
193 nRes = CreateCheckableStuffedFile(TheFs, buf, KCheckFileSize); |
|
194 test_KErrNone(nRes); |
|
195 } |
|
196 |
|
197 return ETrue; |
|
198 } |
|
199 |
|
200 /** |
|
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. |
|
203 |
|
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 |
|
206 */ |
|
207 static TUint32 DoMeasureMountTime(TStressFN apStressFN) |
|
208 { |
|
209 |
|
210 TInt nRes; |
|
211 |
|
212 TTime timeStart; |
|
213 TTime timeEnd; |
|
214 |
|
215 TInt64 usMountTime=0; //-- total time taken by "Mount" |
|
216 |
|
217 //-- disable FAT test utils print out, it can affects measured time |
|
218 EnablePrintOutput(EFalse); |
|
219 |
|
220 for(TInt i=0; i<KBM_Repetitions; ++i) |
|
221 { |
|
222 |
|
223 //-- A. remount FS taking the time when mounting starts |
|
224 nRes = RemountFS(TheFs, gDriveNum, &timeStart); |
|
225 test_KErrNone(nRes); |
|
226 |
|
227 //-- B. call a given stress function |
|
228 if(apStressFN) |
|
229 apStressFN(i); |
|
230 |
|
231 //-- C. take end time |
|
232 timeEnd.UniversalTime(); |
|
233 test_KErrNone(nRes); |
|
234 |
|
235 usMountTime += (timeEnd.MicroSecondsFrom(timeStart)).Int64(); |
|
236 } |
|
237 |
|
238 const TUint32 msMountTime = (TUint32)usMountTime / (K1mSec*KBM_Repetitions); |
|
239 |
|
240 EnablePrintOutput(ETrue); //-- Enable FAT test utils print out |
|
241 |
|
242 return msMountTime; |
|
243 } |
|
244 |
|
245 //------------------------------------------------------------------- |
|
246 |
|
247 /** |
|
248 Stress function. |
|
249 Use case: read access to the first file on the volume in root dir. |
|
250 */ |
|
251 static void FirstReadAccess_FirstFile_Stress(TInt aRepNo) |
|
252 { |
|
253 TBuf<64> buf; |
|
254 buf.Format(KFileNameFirst, aRepNo); |
|
255 |
|
256 TInt nRes = VerifyCheckableFile(TheFs, buf); |
|
257 test_KErrNone(nRes); |
|
258 } |
|
259 |
|
260 |
|
261 /** |
|
262 Stress function. |
|
263 Use case: read access to the middle file on the volume in root dir. |
|
264 */ |
|
265 static void FirstReadAccess_MiddleFile_Stress(TInt aRepNo) |
|
266 { |
|
267 TBuf<64> buf; |
|
268 buf.Format(KFileNameMiddle, aRepNo); |
|
269 |
|
270 TInt nRes = VerifyCheckableFile(TheFs, buf); |
|
271 test_KErrNone(nRes); |
|
272 } |
|
273 |
|
274 /** |
|
275 Stress function. |
|
276 Use case: read access to the last file on the volume in root dir. |
|
277 */ |
|
278 static void FirstReadAccess_LastFile_Stress(TInt aRepNo) |
|
279 { |
|
280 TBuf<64> buf; |
|
281 buf.Format(KFileNameLast, aRepNo); |
|
282 |
|
283 TInt nRes = VerifyCheckableFile(TheFs, buf); |
|
284 test_KErrNone(nRes); |
|
285 } |
|
286 |
|
287 /** |
|
288 Stress function. |
|
289 Use case: Getting volume information SYNCHRONOUSLY. |
|
290 */ |
|
291 static void GetVolInfo_Synch_Stress(TInt) |
|
292 { |
|
293 TVolumeInfo volInfo; |
|
294 TInt nRes = TheFs.Volume(volInfo, gDriveNum); |
|
295 test_KErrNone(nRes); |
|
296 } |
|
297 |
|
298 /** |
|
299 Stress function. |
|
300 Use case: Getting volume information _ASYNCHRONOUSLY_, i.e. do not wait until |
|
301 FAT32 free space scan thread finishes |
|
302 */ |
|
303 static void GetVolInfo_Asynch_Stress(TInt) |
|
304 { |
|
305 TVolumeInfo volInfo; |
|
306 |
|
307 //-- let's use special version of the RFS API |
|
308 TRequestStatus rqStat; |
|
309 TheFs.Volume(volInfo, gDriveNum, rqStat); |
|
310 |
|
311 User::WaitForRequest(rqStat); |
|
312 test(rqStat.Int()==KErrNone); |
|
313 |
|
314 } |
|
315 |
|
316 //------------------------------------------------------------------- |
|
317 |
|
318 /** |
|
319 Stress function. |
|
320 Use case: deletes files in the beginning of the volume (or FAT table) |
|
321 */ |
|
322 static void DeleteFirstFile_Stress(TInt aRepNo) |
|
323 { |
|
324 TBuf<64> buf; |
|
325 buf.Format(KFileNameFirst, aRepNo); |
|
326 |
|
327 TInt nRes = TheFs.Delete(buf); |
|
328 test_KErrNone(nRes); |
|
329 } |
|
330 |
|
331 |
|
332 /** |
|
333 Stress function. |
|
334 Use case: deletes files in the middle of the volume (or FAT table) |
|
335 */ |
|
336 static void DeleteMiddleFile_Stress(TInt aRepNo) |
|
337 { |
|
338 TBuf<64> buf; |
|
339 buf.Format(KFileNameMiddle, aRepNo); |
|
340 |
|
341 TInt nRes = TheFs.Delete(buf); |
|
342 test_KErrNone(nRes); |
|
343 } |
|
344 |
|
345 /** |
|
346 Stress function. |
|
347 Use case: deletes files in the end of the volume (or FAT table) |
|
348 */ |
|
349 static void DeleteLastFile_Stress(TInt aRepNo) |
|
350 { |
|
351 TBuf<64> buf; |
|
352 buf.Format(KFileNameLast, aRepNo); |
|
353 |
|
354 TInt nRes = TheFs.Delete(buf); |
|
355 test_KErrNone(nRes); |
|
356 } |
|
357 |
|
358 |
|
359 //------------------------------------------------------------------- |
|
360 |
|
361 /** |
|
362 perform series of tests that measure and print out FAT volume mount time for different secenarios |
|
363 */ |
|
364 void MeasureMountTime() |
|
365 { |
|
366 TUint32 msTime; |
|
367 |
|
368 if(!PrepareVolumeForBM()) //-- prepare the volume for BM tests: format it, create file structure etc. |
|
369 return; |
|
370 |
|
371 //-- 1. no stress function, measure just pure mount time |
|
372 msTime = DoMeasureMountTime(NULL); |
|
373 test.Printf(_L("#--> Pure mount:%d ms\n"), msTime); |
|
374 |
|
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); |
|
378 |
|
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); |
|
382 |
|
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); |
|
386 |
|
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); |
|
390 |
|
391 msTime = DoMeasureMountTime(GetVolInfo_Asynch_Stress); |
|
392 test.Printf(_L("#--> mount and getting volInfo (Asynch):%d ms\n"), msTime); |
|
393 |
|
394 |
|
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); |
|
398 |
|
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); |
|
402 |
|
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); |
|
406 |
|
407 test.Printf(_L("---\n"), msTime); |
|
408 } |
|
409 |
|
410 //---------------------------------------------------------------------------------------------- |
|
411 //! @SYMTestCaseID PBASE-T_MOUNT-0521 |
|
412 //! @SYMTestType PT |
|
413 //! @SYMPREQ PREQ1721 |
|
414 //! @SYMTestCaseDesc Testing FAT volume mount performance for various scenarios |
|
415 //! |
|
416 //! @SYMTestActions |
|
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: |
|
420 //! a. simple mount |
|
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 |
|
424 //! |
|
425 //! |
|
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() |
|
433 { |
|
434 test.Next(_L("\n#--> Measuring FAT volumes mount performance.\n")); |
|
435 #ifndef _DEBUG |
|
436 test.Printf(_L("Skipping the test in the Release build! \n")); |
|
437 return; |
|
438 #else |
|
439 |
|
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); |
|
443 MeasureMountTime(); |
|
444 |
|
445 //-- 2. Turn ON using FSInfo |
|
446 test.Printf(_L("#--> ==== Enabled Using FSInfo ====\n")); |
|
447 SetFsyDebugFlag(gDriveNum, KMntProp_DisableALL & ~KMntProp_Disable_FsInfo); |
|
448 MeasureMountTime(); |
|
449 |
|
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); |
|
453 MeasureMountTime(); |
|
454 |
|
455 //-- restore mounting mechanism |
|
456 SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL); |
|
457 |
|
458 #endif //_DEBUG |
|
459 } |
|
460 |
|
461 |
|
462 |
|
463 //------------------------------------------------------------------- |
|
464 |
|
465 /** |
|
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. |
|
468 |
|
469 @param aDriveNo drive number to query. |
|
470 @return ETrue if the drive if finalised |
|
471 */ |
|
472 static TBool DoCheckVolumeFinalised(TInt aDriveNo) |
|
473 { |
|
474 TInt nRes; |
|
475 TPckgBuf<TBool> boolPckg; |
|
476 |
|
477 //-- 1. get "Finalised" state by using the API |
|
478 nRes = TheFs.QueryVolumeInfoExt(aDriveNo, EIsDriveFinalised, boolPckg); |
|
479 test_KErrNone(nRes); |
|
480 |
|
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] |
|
484 |
|
485 const TBool bFinalised_From_API = boolPckg() >0; |
|
486 TBool bFinalised_From_FAT1 = bFinalised_From_API; |
|
487 |
|
488 TBuf8<32> fatBuf(32); |
|
489 TFatBootSector bootSec; |
|
490 const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2; |
|
491 |
|
492 nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, bootSec); |
|
493 test_KErrNone(nRes); |
|
494 |
|
495 test(bootSec.IsValid()); |
|
496 |
|
497 const TUint32 Fat1StartPos = bootSec.FirstFatSector() * bootSec.BytesPerSector(); |
|
498 |
|
499 if(bootSec.FatType() == EFat16) |
|
500 {//-- FAT16 |
|
501 TUint16 fatEntry; |
|
502 const TUint16 KClnShtdnMask = 0x8000; //-- "ClnShutBitMask", see FAT specs |
|
503 |
|
504 //-- read "CleanShutDown" flag directly from the 1st FAT |
|
505 nRes = MediaRawRead(TheFs, gDriveNum, Fat1StartPos, fatBuf.Size(), fatBuf); |
|
506 test_KErrNone(nRes); |
|
507 |
|
508 Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry)); |
|
509 bFinalised_From_FAT1 = (fatEntry & KClnShtdnMask) >0; |
|
510 |
|
511 |
|
512 for(TInt i=1; i<bootSec.NumberOfFats(); ++i) |
|
513 { |
|
514 //-- read a flag from the next FAT |
|
515 const TUint32 currFatStartPos = (bootSec.FirstFatSector() + i*bootSec.TotalFatSectors())*bootSec.BytesPerSector(); |
|
516 |
|
517 nRes = MediaRawRead(TheFs, gDriveNum, currFatStartPos, fatBuf.Size(), fatBuf); |
|
518 test_KErrNone(nRes); |
|
519 |
|
520 Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry)); |
|
521 const TBool bFinalised_From_currFAT = (fatEntry & KClnShtdnMask)>0; |
|
522 |
|
523 test(bFinalised_From_currFAT == bFinalised_From_FAT1); |
|
524 } |
|
525 |
|
526 } |
|
527 else if(bootSec.FatType() == EFat32) |
|
528 {//-- FAT32 |
|
529 TUint32 fatEntry; |
|
530 const TUint32 KClnShtdnMask = 0x08000000; //-- "ClnShutBitMask", see FAT specs |
|
531 |
|
532 //-- read "CleanShutDown" flag directly from the 1st FAT |
|
533 nRes = MediaRawRead(TheFs, gDriveNum, Fat1StartPos, fatBuf.Size(), fatBuf); |
|
534 test_KErrNone(nRes); |
|
535 |
|
536 Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry)); |
|
537 bFinalised_From_FAT1 = (fatEntry & KClnShtdnMask) >0; |
|
538 |
|
539 for(TInt i=1; i<bootSec.NumberOfFats(); ++i) |
|
540 { |
|
541 //-- read a flag from the next FAT |
|
542 const TUint32 currFatStartPos = (bootSec.FirstFatSector() + i*bootSec.TotalFatSectors())*bootSec.BytesPerSector(); |
|
543 |
|
544 nRes = MediaRawRead(TheFs, gDriveNum, currFatStartPos, fatBuf.Size(), fatBuf); |
|
545 test_KErrNone(nRes); |
|
546 |
|
547 Mem::Copy(&fatEntry, (fatBuf.Ptr()+sizeof(fatEntry)), sizeof(fatEntry)); |
|
548 const TBool bFinalised_From_currFAT = (fatEntry & KClnShtdnMask) >0; |
|
549 |
|
550 test(bFinalised_From_currFAT == bFinalised_From_FAT1); |
|
551 } |
|
552 |
|
553 } |
|
554 else //-- FAT12 |
|
555 {//-- FAT12 doesn't have flags in FAT[1] |
|
556 bFinalised_From_FAT1 = bFinalised_From_API; |
|
557 } |
|
558 |
|
559 test(bFinalised_From_FAT1 == bFinalised_From_API); |
|
560 |
|
561 return bFinalised_From_API; |
|
562 } |
|
563 |
|
564 |
|
565 |
|
566 //---------------------------------------------------------------------------------------------- |
|
567 //! @SYMTestCaseID PBASE-T_MOUNT-0522 |
|
568 //! @SYMTestType UT |
|
569 //! @SYMPREQ PREQ1721 |
|
570 //! @SYMTestCaseDesc RFs::FinaliseDrive() and RFs::FinaliseDrives() API |
|
571 //! |
|
572 //! @SYMTestActions |
|
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 |
|
589 //! |
|
590 //! @SYMTestExpectedResults finishes if the volume finalisation works correctly. panics otherwise |
|
591 //! @SYMTestPriority High |
|
592 //! @SYMTestStatus Implemented |
|
593 //---------------------------------------------------------------------------------------------- |
|
594 static void TestFinaliseFS() |
|
595 { |
|
596 test.Next(_L("Testing RFs::FinaliseDrives() API\n")); |
|
597 |
|
598 if(!Is_Fat16(TheFs, gDriveNum) && !Is_Fat32(TheFs, gDriveNum)) |
|
599 { |
|
600 test.Printf(_L("This step requires FAT16 or FAT32 ! Skipping.\n")); |
|
601 return; |
|
602 } |
|
603 |
|
604 TInt nRes; |
|
605 TBool bDriveFinalised; |
|
606 |
|
607 //============= 1. finalise the drive (RW mode) and check the result |
|
608 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW); |
|
609 test_KErrNone(nRes); |
|
610 |
|
611 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
612 test(bDriveFinalised); |
|
613 |
|
614 //-- 1.1 finalise the drive second time EFinal_RW -> EFinal_RW shall work |
|
615 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW); |
|
616 test_KErrNone(nRes); |
|
617 |
|
618 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
619 test(bDriveFinalised); |
|
620 |
|
621 //============= 2. create a file. Shall succeed (EFinal_RW), the volume shall become unfinalised |
|
622 |
|
623 RFile file; |
|
624 _LIT(KFileName, "\\my_file1.dat"); |
|
625 |
|
626 nRes = CreateEmptyFile(TheFs, KFileName, 128000); |
|
627 test_KErrNone(nRes); |
|
628 |
|
629 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
630 test(!bDriveFinalised); //-- the volume has become "unfinalised" |
|
631 |
|
632 //-- 2.1 open a file, try to finalise; Shall dail with KErrInUse |
|
633 nRes = file.Replace(TheFs, KFileName, EFileWrite | EFileRead); |
|
634 test_KErrNone(nRes); |
|
635 |
|
636 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW); |
|
637 test(nRes==KErrInUse); //-- can't finalise drives with opened objects |
|
638 |
|
639 file.Close(); |
|
640 |
|
641 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW); |
|
642 test_KErrNone(nRes); |
|
643 |
|
644 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
645 test(bDriveFinalised); |
|
646 |
|
647 //============= 3. test "unfinalise API" |
|
648 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EForceUnfinalise); |
|
649 test_KErrNone(nRes); |
|
650 |
|
651 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
652 test(!bDriveFinalised); //-- the volume has become "unfinalised" |
|
653 |
|
654 //============= 4. test finalisation into RO mode |
|
655 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RO); //-- the volume becomes RO |
|
656 test_KErrNone(nRes); |
|
657 |
|
658 //-- try to write a file on RO volume; it shall fail with KErrAccessDenied |
|
659 nRes = CreateEmptyFile(TheFs, KFileName, 128000); |
|
660 test(nRes == KErrAccessDenied); |
|
661 file.Close(); |
|
662 |
|
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); |
|
666 |
|
667 //-- 4.2 "unfinalise" the volume, it still shall remain RO |
|
668 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EForceUnfinalise); |
|
669 test_KErrNone(nRes); |
|
670 |
|
671 //-- try to write a file on RO volume; it shall fail with KErrAccessDenied |
|
672 nRes = CreateEmptyFile(TheFs, KFileName, 128000); |
|
673 test(nRes == KErrAccessDenied); |
|
674 file.Close(); |
|
675 |
|
676 //-- remount FS, the drive shall become RW |
|
677 nRes = RemountFS(TheFs, gDriveNum); |
|
678 test_KErrNone(nRes); |
|
679 |
|
680 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
681 test(bDriveFinalised); |
|
682 |
|
683 //-- try to write a file on RW volume, shall be OK |
|
684 nRes = CreateEmptyFile(TheFs, KFileName, 128000); |
|
685 test(nRes == KErrNone); |
|
686 file.Close(); |
|
687 |
|
688 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
689 test(!bDriveFinalised); |
|
690 |
|
691 //============= 5. test various finalisation modes |
|
692 |
|
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); |
|
698 |
|
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); |
|
704 |
|
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); |
|
710 |
|
711 //-- 5.3 restore |
|
712 nRes = RemountFS(TheFs, gDriveNum); |
|
713 test_KErrNone(nRes); |
|
714 |
|
715 |
|
716 //============= 6. test old RFs::FinaliseDrives API |
|
717 |
|
718 nRes = CreateEmptyFile(TheFs, KFileName, 128000); |
|
719 test(nRes == KErrNone); |
|
720 |
|
721 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
722 test(!bDriveFinalised); |
|
723 |
|
724 TheFs.FinaliseDrives(); //-- shall work as TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW) but for ALL drives |
|
725 |
|
726 bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
727 test(bDriveFinalised); |
|
728 |
|
729 nRes = CreateEmptyFile(TheFs, KFileName, 128000); |
|
730 test(nRes == KErrNone); |
|
731 |
|
732 } |
|
733 |
|
734 //---------------------------------------------------------------------------------------------- |
|
735 //! @SYMTestCaseID PBASE-T_MOUNT-0523 |
|
736 //! @SYMTestType UT |
|
737 //! @SYMPREQ PREQ1721 |
|
738 //! @SYMTestCaseDesc testing boot and backup boot sectors on FAT32 volume |
|
739 //! |
|
740 //! @SYMTestActions |
|
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 |
|
746 //! |
|
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() |
|
752 { |
|
753 test.Next(_L("Testing Backup Boot Sector.\n")); |
|
754 |
|
755 TInt nRes; |
|
756 |
|
757 //-- quick format the drive |
|
758 FormatVolume(ETrue); |
|
759 |
|
760 if(!Is_Fat32(TheFs, gDriveNum)) |
|
761 { |
|
762 test.Printf(_L("This step requires FAT32 ! Skipping.\n")); |
|
763 return; |
|
764 } |
|
765 |
|
766 TFatBootSector mainBootSec, backupBootSec; |
|
767 TFSInfo mainFSInfo, backupFSInfo; |
|
768 |
|
769 const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2; |
|
770 const TUint32 posBkBootSec = KBkBootSectorNum << KDefaultSectorLog2; |
|
771 |
|
772 //-- read main and backup boot & fsinfo sectors and check their validity |
|
773 nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, mainBootSec); |
|
774 test_KErrNone(nRes); |
|
775 |
|
776 //-- backup boot sector # must be 6 |
|
777 nRes = ReadBootSector(TheFs, gDriveNum, posBkBootSec, backupBootSec); |
|
778 test_KErrNone(nRes); |
|
779 |
|
780 test(mainBootSec.IsValid()); |
|
781 test(backupBootSec.IsValid()); |
|
782 test(mainBootSec == backupBootSec); |
|
783 |
|
784 //-- read fsinfo sectors |
|
785 const TUint32 posMainFSInfo = mainBootSec.FSInfoSectorNum() << KDefaultSectorLog2; |
|
786 const TUint32 posBkFSInfo = (KBkBootSectorNum + mainBootSec.FSInfoSectorNum()) << KDefaultSectorLog2; |
|
787 |
|
788 test(posMainFSInfo != 0); |
|
789 test(posBkFSInfo != 0); |
|
790 |
|
791 nRes = ReadFSInfoSector(TheFs, gDriveNum, posMainFSInfo, mainFSInfo); |
|
792 test_KErrNone(nRes); |
|
793 |
|
794 nRes = ReadFSInfoSector(TheFs, gDriveNum, posBkFSInfo, backupFSInfo); |
|
795 test_KErrNone(nRes); |
|
796 |
|
797 test(mainFSInfo.IsValid()); |
|
798 test(backupFSInfo.IsValid()); |
|
799 test(mainFSInfo == backupFSInfo); |
|
800 |
|
801 //-- corrupt main boot sector and check that the drive can be mounted |
|
802 test.Printf(_L("Corrupting main boot sector...\n")); |
|
803 |
|
804 |
|
805 //-- A1. corrupt main boot sector starting from the pos:0 |
|
806 nRes = FillMedia(TheFs, gDriveNum, posMainBootSec, posMainBootSec+KDefaultSectorSize, 0xaa); |
|
807 |
|
808 //-- A2. remount FS, it shall be OK because of the using backup boot sector |
|
809 nRes = RemountFS(TheFs, gDriveNum); |
|
810 test_KErrNone(nRes); |
|
811 |
|
812 |
|
813 //-- B1. corrupt BACKUP boot sector starting from the sec:6 |
|
814 nRes = FillMedia(TheFs, gDriveNum, posBkBootSec, posBkBootSec+KDefaultSectorSize, 0xbb); |
|
815 |
|
816 //-- B2. remount FS, unable to mount. |
|
817 nRes = RemountFS(TheFs, gDriveNum); |
|
818 test(nRes == KErrCorrupt); |
|
819 |
|
820 |
|
821 //-- quick format the drive |
|
822 FormatVolume(ETrue); |
|
823 |
|
824 } |
|
825 |
|
826 //---------------------------------------------------------------------------------------------- |
|
827 //! @SYMTestCaseID PBASE-T_MOUNT-0524 |
|
828 //! @SYMTestType UT |
|
829 //! @SYMPREQ PREQ1721 |
|
830 //! @SYMTestCaseDesc testing FSInfo sector functionality. |
|
831 //! |
|
832 //! @SYMTestActions |
|
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 |
|
839 //! |
|
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() |
|
845 { |
|
846 test.Next(_L("Testing FSInfo Sector.\n")); |
|
847 |
|
848 #ifndef _DEBUG |
|
849 test.Printf(_L("Skipping the test in the Release build! \n")); |
|
850 return; |
|
851 #else |
|
852 |
|
853 TInt nRes; |
|
854 |
|
855 //-- quick format the drive |
|
856 FormatVolume(ETrue); |
|
857 |
|
858 if(!Is_Fat32(TheFs, gDriveNum)) |
|
859 { |
|
860 test.Printf(_L("This step requires FAT32 ! Skipping.\n")); |
|
861 return; |
|
862 } |
|
863 |
|
864 TFatBootSector bootSec; |
|
865 const TUint32 posMainBootSec = KBootSectorNum << KDefaultSectorLog2; |
|
866 nRes = ReadBootSector(TheFs, gDriveNum, posMainBootSec, bootSec); |
|
867 test_KErrNone(nRes); |
|
868 |
|
869 const TUint32 bytesPerSector = bootSec.BytesPerSector(); |
|
870 const TUint32 secPerClust = bootSec.SectorsPerCluster(); |
|
871 |
|
872 //-- finalise the drive, just in case |
|
873 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW); |
|
874 test_KErrNone(nRes); |
|
875 |
|
876 //============= 1. read FSInfo sector and its backup copy and compare them |
|
877 TFSInfo fsInfoSec; |
|
878 |
|
879 //-- main FSInfo |
|
880 nRes = ReadFSInfoSector(TheFs, gDriveNum, KFSInfoSectorNum*bytesPerSector, fsInfoSec); |
|
881 test_KErrNone(nRes); |
|
882 test(fsInfoSec.IsValid()); |
|
883 |
|
884 TUint32 freeClusters_FSInfo = fsInfoSec.FreeClusterCount(); |
|
885 TUint32 nextFree_FSInfo = fsInfoSec.NextFreeCluster(); |
|
886 |
|
887 //-- backup FSInfo |
|
888 nRes = ReadFSInfoSector(TheFs, gDriveNum, KBkFSInfoSectorNum*bytesPerSector, fsInfoSec); |
|
889 test_KErrNone(nRes); |
|
890 test(fsInfoSec.IsValid()); |
|
891 |
|
892 //-- both copies must be identical |
|
893 test(freeClusters_FSInfo == fsInfoSec.FreeClusterCount()); |
|
894 test(nextFree_FSInfo == fsInfoSec.NextFreeCluster()); |
|
895 |
|
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)); |
|
898 |
|
899 //============= 2. check that after the formatting FS info values are the same as real. |
|
900 |
|
901 //-- 2.1 disable using FSInfo and other stuff |
|
902 SetFsyDebugFlag(gDriveNum, KMntProp_Disable_FsInfo); |
|
903 |
|
904 //-- remount FAT; using FSInfo is disabled. FAT will be explicitly scanned. |
|
905 nRes = RemountFS(TheFs, gDriveNum); |
|
906 test_KErrNone(nRes); |
|
907 |
|
908 //-- restore mounting mechanism |
|
909 SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL); |
|
910 |
|
911 //-- get free clusters number from the FSY, which in turn had counted them explicitly |
|
912 TVolumeInfo volInfo; |
|
913 nRes = TheFs.Volume(volInfo, gDriveNum); |
|
914 test_KErrNone(nRes); |
|
915 |
|
916 TUint32 freeClusters = (TUint32)(volInfo.iFree / (bytesPerSector * secPerClust)); |
|
917 test(freeClusters == freeClusters_FSInfo); |
|
918 |
|
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); |
|
924 test_KErrNone(nRes); |
|
925 |
|
926 //-- 3.1 get data from FS |
|
927 nRes = TheFs.Volume(volInfo, gDriveNum); |
|
928 test_KErrNone(nRes); |
|
929 freeClusters = (TUint32)(volInfo.iFree / (bytesPerSector * secPerClust)); |
|
930 |
|
931 //-- 3.2 finalise the volume and get data from FSInfo |
|
932 nRes =TheFs.FinaliseDrive(gDriveNum, RFs::EFinal_RW); |
|
933 test_KErrNone(nRes); |
|
934 |
|
935 //-- main FSInfo |
|
936 nRes = ReadFSInfoSector(TheFs, gDriveNum, KFSInfoSectorNum*bytesPerSector, fsInfoSec); |
|
937 test_KErrNone(nRes); |
|
938 test(fsInfoSec.IsValid()); |
|
939 |
|
940 freeClusters_FSInfo = fsInfoSec.FreeClusterCount(); |
|
941 nextFree_FSInfo = fsInfoSec.NextFreeCluster(); |
|
942 |
|
943 //-- backup FSInfo |
|
944 nRes = ReadFSInfoSector(TheFs, gDriveNum, KBkFSInfoSectorNum*bytesPerSector, fsInfoSec); |
|
945 test_KErrNone(nRes); |
|
946 test(fsInfoSec.IsValid()); |
|
947 |
|
948 //-- both copies must be identical |
|
949 test(freeClusters_FSInfo == fsInfoSec.FreeClusterCount()); |
|
950 test(nextFree_FSInfo == fsInfoSec.NextFreeCluster()); |
|
951 |
|
952 //-- the information in FSInfo must be the same as in FAT |
|
953 test(freeClusters == freeClusters_FSInfo); |
|
954 |
|
955 TBool bDriveFinalised = DoCheckVolumeFinalised(gDriveNum); |
|
956 test(bDriveFinalised); |
|
957 |
|
958 TheFs.Delete(KFileName); |
|
959 |
|
960 //-- restore mounting mechanism |
|
961 SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL); |
|
962 |
|
963 #endif //_DEBUG |
|
964 } |
|
965 |
|
966 //------------------------------------------------------------------- |
|
967 |
|
968 /** initialise test global objects */ |
|
969 static void InitGlobals() |
|
970 { |
|
971 TInt nRes; |
|
972 |
|
973 //-- define a propery which will control mount process in the fsy. |
|
974 //-- The property key is a drive number being tested |
|
975 |
|
976 _LIT_SECURITY_POLICY_PASS(KTestPropPolicy); |
|
977 nRes = RProperty::Define(KThisTestSID, gDriveNum, RProperty::EInt, KTestPropPolicy, KTestPropPolicy); |
|
978 test(nRes == KErrNone || nRes == KErrAlreadyExists); |
|
979 |
|
980 nRes = RProperty::Set(KThisTestSID, gDriveNum, KMntProp_EnableALL); |
|
981 test_KErrNone(nRes); |
|
982 |
|
983 gRndSeed = Math::Random(); |
|
984 (void)&gRndSeed; //-- get rid of warning |
|
985 } |
|
986 |
|
987 /** destroy test global objects */ |
|
988 static void DestroyGlobals() |
|
989 { |
|
990 //-- delete test property |
|
991 RProperty::Delete(KThisTestSID, gDriveNum); |
|
992 |
|
993 TVolumeInfo v; |
|
994 TheFs.Volume(v); |
|
995 } |
|
996 |
|
997 //------------------------------------------------------------------- |
|
998 /** |
|
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. |
|
1001 */ |
|
1002 void Manual_TestRemount_On_MediaRemoval() |
|
1003 { |
|
1004 TInt nRes; |
|
1005 |
|
1006 _LIT(KFileName, "\\my_file1.dat"); |
|
1007 const TUint32 KFileSz = K1MegaByte; |
|
1008 |
|
1009 //-- 1. create a file |
|
1010 nRes = CreateEmptyFile(TheFs, KFileName, KFileSz); |
|
1011 test_KErrNone(nRes); |
|
1012 |
|
1013 RFile file; |
|
1014 |
|
1015 nRes = file.Open(TheFs, KFileName, EFileRead | EFileWrite); |
|
1016 test_KErrNone(nRes); |
|
1017 |
|
1018 TBuf8<512> buf(512); |
|
1019 TVolumeInfo vi; |
|
1020 buf.FillZ(); |
|
1021 |
|
1022 TKeyCode key; |
|
1023 |
|
1024 for(;;) |
|
1025 { |
|
1026 TheFs.SetDebugRegister(0x00); |
|
1027 |
|
1028 nRes = file.Read(0, buf); |
|
1029 |
|
1030 test.Printf(_L("Remove the media and press a key.\n")); |
|
1031 key = test.Getch(); |
|
1032 if(key == EKeyEscape) |
|
1033 break; |
|
1034 |
|
1035 TheFs.SetDebugRegister(KFSYS | KFSERV); |
|
1036 nRes = file.Read(0, buf); |
|
1037 |
|
1038 if(nRes != KErrNone) |
|
1039 { |
|
1040 |
|
1041 test.Printf(_L("ReadFile: %d!\n"), nRes); |
|
1042 |
|
1043 key = test.Getch(); |
|
1044 if(key == EKeyEscape) |
|
1045 break; |
|
1046 |
|
1047 nRes = TheFs.Volume(vi,gDriveNum); |
|
1048 test.Printf(_L("Volume: %d!\n"), nRes); |
|
1049 |
|
1050 key = test.Getch(); |
|
1051 if(key == EKeyEscape) |
|
1052 break; |
|
1053 |
|
1054 nRes = file.Write(0, buf); |
|
1055 test.Printf(_L("WriteFile: %d!\n"), nRes); |
|
1056 |
|
1057 key = test.Getch(); |
|
1058 if(key == EKeyEscape) |
|
1059 break; |
|
1060 |
|
1061 } |
|
1062 |
|
1063 } |
|
1064 |
|
1065 |
|
1066 file.Close(); |
|
1067 } |
|
1068 |
|
1069 |
|
1070 //------------------------------------------------------------------- |
|
1071 /** |
|
1072 Wait for the request aRqStat to be completed with timeout. |
|
1073 |
|
1074 @param aRqStat request status object we need to wait to complete |
|
1075 @param aTimeout_uS timeout in microseconds |
|
1076 |
|
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. |
|
1079 */ |
|
1080 TBool WaitForRequestWithTimeout(TRequestStatus& aRqStat, TUint32 aTimeout_uS) |
|
1081 { |
|
1082 TRequestStatus rqStatTimeout(KRequestPending); |
|
1083 RTimer tmrTimeOut; |
|
1084 TInt nRes; |
|
1085 TBool bReqCompleted; |
|
1086 |
|
1087 if(aRqStat.Int() != KRequestPending) |
|
1088 return ETrue; //-- nothing to wait for. |
|
1089 |
|
1090 //-- set up a timeout timer |
|
1091 nRes = tmrTimeOut.CreateLocal(); |
|
1092 test(nRes == KErrNone); |
|
1093 |
|
1094 tmrTimeOut.After(rqStatTimeout, aTimeout_uS); |
|
1095 |
|
1096 User::WaitForRequest(aRqStat, rqStatTimeout); |
|
1097 |
|
1098 if(aRqStat == KRequestPending) |
|
1099 {//-- timeout. |
|
1100 bReqCompleted = EFalse; |
|
1101 } |
|
1102 else |
|
1103 {//-- the main request has been completed, cancel timer |
|
1104 bReqCompleted = ETrue; |
|
1105 if(rqStatTimeout.Int() == KRequestPending) |
|
1106 { |
|
1107 tmrTimeOut.Cancel(); |
|
1108 User::WaitForRequest(rqStatTimeout); |
|
1109 } |
|
1110 } |
|
1111 |
|
1112 tmrTimeOut.Close(); |
|
1113 |
|
1114 return bReqCompleted; |
|
1115 } |
|
1116 |
|
1117 //------------------------------------------------------------------- |
|
1118 |
|
1119 void TestNotifyDiskSpace() |
|
1120 { |
|
1121 test.Next(_L("Testing NotifyDiskSpace() on asynchronous mounting\n")); |
|
1122 |
|
1123 #ifndef _DEBUG |
|
1124 test.Printf(_L("Skipping the test in the Release build! \n")); |
|
1125 return; |
|
1126 #else |
|
1127 |
|
1128 TInt nRes; |
|
1129 TRequestStatus rqStat; |
|
1130 TVolumeInfo volInfo; |
|
1131 |
|
1132 //-- quick format the drive |
|
1133 FormatVolume(ETrue); |
|
1134 |
|
1135 if(!Is_Fat32(TheFs, gDriveNum)) |
|
1136 {//-- only FAT32 supports asynch mounting; |
|
1137 test.Printf(_L("This test step requires FAT32!\n")); |
|
1138 return; |
|
1139 } |
|
1140 |
|
1141 //-- FAT32 free space threshold that is supposed to be triggered by notifiers |
|
1142 const TInt64 KFreeSpaceThreshold = 300*K1MegaByte; |
|
1143 |
|
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); |
|
1148 |
|
1149 |
|
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); |
|
1153 |
|
1154 //TheFs.SetDebugRegister(0x03); |
|
1155 |
|
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...")); |
|
1158 |
|
1159 nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it must cause FAT32 free space scan in background |
|
1160 test_KErrNone(nRes); |
|
1161 |
|
1162 test.Printf(_L("Waiting for %LU bytes available on the volume...\n"), KFreeSpaceThreshold); |
|
1163 |
|
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); |
|
1169 |
|
1170 if(volInfo.iSize <= KFreeSpaceThreshold) |
|
1171 { |
|
1172 test.Printf(_L("The volume is too small for %LU bytes notify ...\n"), KFreeSpaceThreshold); |
|
1173 test.Printf(_L("The test is inconclusive ...\n")); |
|
1174 return; |
|
1175 } |
|
1176 |
|
1177 if(volInfo.iFree >= KFreeSpaceThreshold) |
|
1178 { |
|
1179 test.Printf(_L("The volume already has %LU free bytes...\n"), volInfo.iFree); |
|
1180 test.Printf(_L("The test is inconclusive ...\n")); |
|
1181 return; |
|
1182 } |
|
1183 |
|
1184 |
|
1185 TheFs.NotifyDiskSpace(KFreeSpaceThreshold, gDriveNum, rqStat); |
|
1186 test(rqStat.Int()==KRequestPending); |
|
1187 |
|
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); |
|
1191 |
|
1192 if(!bCompleted) |
|
1193 { |
|
1194 test.Printf(_L("Wait timeout! something is wrong...\n")); |
|
1195 test(0); |
|
1196 } |
|
1197 |
|
1198 test_KErrNone(rqStat.Int()); |
|
1199 |
|
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); |
|
1205 |
|
1206 |
|
1207 //===== Test that aborting FAT32 free space scanning thread will trigger notifiers |
|
1208 test.Printf(_L("Testing aborting FAT32 free space scanning thread...")); |
|
1209 |
|
1210 nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it must cause FAT32 free space scan in background |
|
1211 test_KErrNone(nRes); |
|
1212 |
|
1213 TheFs.NotifyDiskSpace(KFreeSpaceThreshold, gDriveNum, rqStat); |
|
1214 test(rqStat.Int()==KRequestPending); |
|
1215 |
|
1216 nRes = RemountFS(TheFs, gDriveNum); //-- remount FS; it will abort the scanning thread |
|
1217 test_KErrNone(nRes); |
|
1218 |
|
1219 test(rqStat.Int() != KRequestPending); |
|
1220 |
|
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); |
|
1226 |
|
1227 |
|
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); |
|
1232 |
|
1233 |
|
1234 //TheFs.SetDebugRegister(0x00); |
|
1235 |
|
1236 //-- restore mounting mechanism |
|
1237 SetFsyDebugFlag(gDriveNum, KMntProp_EnableALL); |
|
1238 |
|
1239 #endif //_DEBUG |
|
1240 } |
|
1241 |
|
1242 //------------------------------------------------------------------- |
|
1243 |
|
1244 void CallTestsL() |
|
1245 { |
|
1246 //-- set up console output |
|
1247 Fat_Test_Utils::SetConsole(test.Console()); |
|
1248 |
|
1249 TInt nRes=TheFs.CharToDrive(gDriveToTest, gDriveNum); |
|
1250 test(nRes==KErrNone); |
|
1251 |
|
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. |
|
1256 |
|
1257 test.Printf(_L("Skipping. This test requires explicitly mounted FAT file system.\n")); |
|
1258 return; |
|
1259 } |
|
1260 |
|
1261 //-- check this is not the internal ram drive |
|
1262 TVolumeInfo v; |
|
1263 |
|
1264 nRes = TheFs.Volume(v); |
|
1265 test(nRes==KErrNone); |
|
1266 if(v.iDrive.iMediaAtt & KMediaAttVariableSize) |
|
1267 { |
|
1268 test.Printf(_L("Skipping. Internal ram drive not tested.\n")); |
|
1269 return; |
|
1270 } |
|
1271 |
|
1272 //------------------------------------- |
|
1273 |
|
1274 PrintDrvInfo(TheFs, gDriveNum); |
|
1275 InitGlobals(); |
|
1276 |
|
1277 |
|
1278 TestNotifyDiskSpace(); |
|
1279 |
|
1280 //------------------------------------- |
|
1281 TestBackupBootSector(); |
|
1282 TestFSInfoSector(); |
|
1283 TestFinaliseFS(); |
|
1284 |
|
1285 //------------------------------------- |
|
1286 TestFAT_Mounting_Performance(); |
|
1287 //------------------------------------- |
|
1288 //-- manual test |
|
1289 //Manual_TestRemount_On_MediaRemoval(); |
|
1290 |
|
1291 //------------------------------------- |
|
1292 DestroyGlobals(); |
|
1293 |
|
1294 } |
|
1295 |
|
1296 |
|
1297 |
|
1298 |
|
1299 |
|
1300 |
|
1301 |
|
1302 |
|
1303 |
|
1304 |
|
1305 |
|
1306 |
|
1307 |
|
1308 |
|
1309 |
|
1310 |
|
1311 |
|
1312 |