First public contribution.
1 // Copyright (c) 2006-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_CHECKDISK.cpp
17 #define __E32TEST_EXTENSION__
23 //#include <e32twin.h>
25 RTest test(_L("T_CHECKDISK"));
29 TFileName gSessionPath;
34 TPtr8 gBufReadPtr(NULL, 0);
35 HBufC8* gBufSec = NULL;
36 TPtr8 gBufWritePtr(NULL, 0);
38 const TInt KOneK = 1024;
39 const TInt KOneMeg = KOneK * 1024;
40 const TInt KBlockSize = KOneK * 129 ;
41 const TInt KWaitRequestsTableSize = 70;
43 TInt gBigFileSize = 0;
44 TInt gSmallFileSize = 0;
45 TInt64 gMediaSize = 0;
47 TInt writeSize = KBlockSize;
49 TSeek seekType = ESeekAddress;
52 TTimeIntervalMicroSeconds32 gTimeTakenBigFile(0);
53 TBuf16<45> gSmallFile, gBigFile;
54 LOCAL_D TInt gNextFile=0;
58 LOCAL_D RSemaphore gSync;
63 LOCAL_D RSemaphore client;
64 LOCAL_D const TInt KHeapSize=0x4000;
65 LOCAL_D const TInt KMaxHeapSize=0x100000;
66 TRequestStatus gStatus[KWaitRequestsTableSize];
76 // Generates a name of the form FFFFF*<aPos>.TXT (aLong.3)
78 GLDEF_C void FileNameGen(TDes16& aBuffer, TInt aLong, TInt aPos)
85 tempbuf.Format(KNumber,aPos);
86 padding=aLong-tempbuf.Size()/2;
93 aBuffer.Append(tempbuf);
95 _LIT(KExtension1, ".TXT");
96 aBuffer.Append(KExtension1);
103 // Expects a drive letter as a parameter
105 LOCAL_C void parseCommandLine()
108 User::CommandLine(cmd);
110 TPtrC token=lex.NextToken();
113 if(token.Length()!=0)
115 gDriveToTest=token[0];
116 gDriveToTest.UpperCase();
123 r=TheFs.CharToDrive(gDriveToTest,gDrive);
125 gSessionPath=_L("?:\\F32-TST\\");
126 gSessionPath[0]=(TText)gDriveToTest;
127 test.Printf(_L("\nCLP=%S\n"),&token);
131 // Fills a buffer with character aC
133 LOCAL_C void FillBuffer(TDes8& aBuffer, TInt aLength, TChar aC)
135 test (aBuffer.MaxLength() >= aLength);
136 for(TInt i=0; i<aLength; i++)
143 // Waits for all the TRequestStatus in status[] to complete
145 LOCAL_C void WaitForAll(TRequestStatus status[], TInt aSize)
151 User::WaitForRequest(status[i++]);
157 // Writes a file synchronously in blocks of aBlockSize size
158 // this function can be called from another thread, therefore requires its own RTest instance
159 LOCAL_C TInt WriteFile(RFs& fs, TDes16& aFile, TInt aSize, TInt aBlockSize, TTestState aState)
166 test(aBlockSize>0); // Block size must be greater than 0
168 if(aState==EThreadWait)
172 r=fileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite);
178 r=fileWrite.Write(gBufWritePtr, writeSize);
182 r=fileWrite.Seek(seekType, seekSize);
185 if (writeSize + reduceSize >= 0)
186 writeSize += reduceSize;
188 writeSize = Min(writeSize, gBufWritePtr.Length());
191 if((j==0)&&(aState==EThreadSignal))
203 LOCAL_C void IniStatus(TRequestStatus aStatus[], TInt aSize)
209 aStatus[i++]=KRequestPending;
215 // This is a thread function, therefore requires its own RTest instance
216 LOCAL_C TInt WriteBigFile(TAny* )
220 TInt r=fs.Connect(gDriveToTest);
223 r=fs.SetSessionPath(gSessionPath);
226 WriteFile(fs, gBigFile, gBigFileSize, KBlockSize, EThreadSignal);
234 // Writes a file asynchronously in blocks of aBlockSize size
235 // this function can be called from another thread, therefore requires its own RTest instance
236 LOCAL_C void WriteFileAsync(RFs& fs, RFile& aFileWrite, TDes16& aFile, TInt aSize, TInt aBlockSize, TRequestStatus aStatus[])
242 test(aBlockSize>0); // Block size must be greater than 0
243 test((aSize%aBlockSize)==0); // Ensure the size of the file is a multiple of the block size
245 r=aFileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite);
251 aFileWrite.Write(gBufWritePtr,aStatus[i++]);
259 // Write big file async
260 // This is a thread function, therefore requires its own RTest instance
261 LOCAL_C TInt WriteBigFileAsync(TAny* )
265 TInt r=fs.Connect(gDriveToTest);
268 r=fs.SetSessionPath(gSessionPath);
274 IniStatus(gStatus,KWaitRequestsTableSize);
275 WriteFileAsync(fs, bigFile, gSmallFile, gBigFileSize, KBlockSize,gStatus);
277 WaitForAll(gStatus, gBigFileSize/KBlockSize);
282 static void TestClientDies()
284 test.Next(_L("Client dying unexpectedly"));
287 TBuf<20> unit=_L("?:\\");
288 unit[0]=(TText)gDriveToTest;
290 //-------------------------------------------
291 test.Printf(_L("Sync test\n"));
293 r=gBig.Create(_L("TEST1"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
303 r=TheFs.CheckDisk(unit);
304 test_Value(r, r == KErrNone || r == KErrNotSupported);
306 //-------------------------------------------
307 test.Printf(_L("Async test\n"));
308 r=gSmall.Create(_L("TEST2"),WriteBigFileAsync,KDefaultStackSize*2,KHeapSize,KMaxHeapSize,NULL);
318 r=TheFs.CheckDisk(unit);
319 test_Value(r, r == KErrNone || r == KErrNotSupported);
321 //-------------------------------------------
322 test.Printf(_L("Testing for size not multiple of blocksize\n"));
325 r=gBig.Create(_L("TEST3"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
334 r=TheFs.CheckDisk(unit);
335 test_Value(r, r == KErrNone || r == KErrNotSupported);
337 //-------------------------------------------
338 test.Printf(_L("Testing with seek current and write inside the file boundary\n"));
341 seekType = ESeekCurrent;
344 r=gBig.Create(_L("TEST4"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
353 r=TheFs.CheckDisk(unit);
354 test_Value(r, r == KErrNone || r == KErrNotSupported);
356 //-------------------------------------------
357 test.Printf(_L("Testing with seek current and overwrite entire file\n"));
359 seekType = ESeekCurrent;
362 r=gBig.Create(_L("TEST5"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
371 r=TheFs.CheckDisk(unit);
372 test_Value(r, r == KErrNone || r == KErrNotSupported);
374 //-------------------------------------------
375 test.Printf(_L("Testing with seek current and write outside the file boundary\n"));
378 seekType = ESeekCurrent;
381 r=gBig.Create(_L("TEST6"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
390 r=TheFs.CheckDisk(unit);
391 test_Value(r, r == KErrNone || r == KErrNotSupported);
393 //-------------------------------------------
394 test.Printf(_L("Testing with seek current and write within the file boundary\n"));
396 seekType = ESeekCurrent;
399 r=gBig.Create(_L("TEST7"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
408 r=TheFs.CheckDisk(unit);
409 test_Value(r, r == KErrNone || r == KErrNotSupported);
411 //-------------------------------------------
412 test.Printf(_L("Testing with seek current and write exactly to file size\n"));
414 seekType = ESeekCurrent;
417 r=gBig.Create(_L("TEST8"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
426 r=TheFs.CheckDisk(unit);
427 test_Value(r, r == KErrNone || r == KErrNotSupported);
429 //-------------------------------------------
430 test.Printf(_L("Testing with seek current and write greater than file size\n"));
432 seekType = ESeekCurrent;
435 r=gBig.Create(_L("TEST9"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
444 r=TheFs.CheckDisk(unit);
445 test_Value(r, r == KErrNone || r == KErrNotSupported);
451 r=TheFs.ScanDrive(unit);
453 test.Printf(_L("ScanDrive() returned %d\n"), r);
457 while (r == KErrInUse && ++retries < 5);
459 test_Value(r, r == KErrNone || r == KErrNotSupported);
464 //---------------------------------------------------------------------
466 Test that CheckDisk will not cause stack overflow on very deep directory structure.
468 void TestCheckDisk_VeryDeepDirectory()
470 test.Next(_L("Testing deep dir structure check"));
473 TBuf<20> unit=_L("?:\\");
474 unit[0]=(TText)gDriveToTest;
476 //-- 1. create deep dir structure, like \\0\\1\\2\\...... 90 levels deep
477 const TInt KMaxDirDepth = 90;
479 test.Printf(_L("Creating directory with %d subdirs.\n"),KMaxDirDepth);
482 for(TInt i=0; i<KMaxDirDepth; ++i)
484 fn.AppendFormat(_L("\\%d"), i%10);
488 nRes = TheFs.MkDirAll(fn);
489 test_Value(nRes, nRes == KErrNone || nRes == KErrAlreadyExists);
491 //-- 2. invoke Check Disk and ensure that target doesn't die from stack overflow.
492 test.Printf(_L("Running Check Disk...\n"));
493 nRes = TheFs.CheckDisk(unit);
495 test_Value(nRes, nRes == KErrNone || nRes == KErrTooBig);
499 //---------------------------------------------------------------------
501 // This test tries to read a small file while writing a big one
503 GLDEF_C void CallTestsL()
507 test.Next(_L("Preparing the environmnet\n"));
509 FileNameGen(gSmallFile, 8, gNextFile++);
510 FileNameGen(gBigFile, 8, gNextFile++);
512 dir.Append(gSmallFile);
515 dir.Append(gBigFile);
518 TRAPD(res,gBuf = HBufC8::NewL(KBlockSize+1));
519 test(res == KErrNone && gBuf != NULL);
521 gBufWritePtr.Set(gBuf->Des());
522 FillBuffer(gBufWritePtr, KBlockSize, 'B');
524 TRAPD(res2,gBufSec = HBufC8::NewL(KBlockSize+1));
525 test(res2 == KErrNone && gBufSec != NULL);
526 gBufReadPtr.Set(gBufSec->Des());
528 //---------------------------
531 TestCheckDisk_VeryDeepDirectory();
537 LOCAL_C void DoTests()
541 r=client.CreateLocal(0);
544 r=gSync.CreateLocal(0);
547 r=TheFs.SetSessionPath(gSessionPath);
550 r=TheFs.MkDirAll(gSessionPath);
551 test_Value(r, r == KErrNone || r == KErrAlreadyExists);
553 TheFs.ResourceCountMarkStart();
554 TRAP(r,CallTestsL());
556 TheFs.ResourceCountMarkEnd();
559 TBool CheckForDiskSize()
562 TInt r = TheFs.Volume(volInfo, gDrive);
565 gMediaSize = volInfo.iSize;
566 gSmallFileSize = KBlockSize;
567 gBigFileSize = KBlockSize*20;
568 while(((2*gBigFileSize)+KOneMeg) > gMediaSize )
570 gBigFileSize -= (2*KBlockSize);
573 if(gBigFileSize< (3*gSmallFileSize))
579 void Format(TInt aDrive)
582 test.Next(_L("Format"));
583 TBuf<4> driveBuf=_L("?:\\");
584 driveBuf[0]=(TText)(aDrive+'A');
587 TInt r=format.Open(TheFs,driveBuf,EQuickFormat,count);
592 TInt r=format.Next(count);
599 static TBool IsFAT(RFs &aFsSession, TInt aDrive)
601 _LIT(KFatName, "Fat");
604 TInt r = aFsSession.FileSystemName(f, aDrive);
605 test_Value(r, r == KErrNone || r == KErrNotFound);
606 return (f.CompareF(KFatName) == 0);
610 GLDEF_C TInt E32Main()
613 CTrapCleanup* cleanup;
614 cleanup=CTrapCleanup::New();
618 test.Start(_L("Starting tests..."));
621 TInt r = TheFs.Connect();
626 r=TheFs.Drive(info,gDrive);
629 if(info.iMediaAtt&KMediaAttVariableSize)
630 {// Not testing in RAM Drives
631 test.Printf(_L("Tests skipped in RAM drive\n"));
635 r = TheFs.Volume(volInfo, gDrive);
636 if (r == KErrNotReady)
638 if (info.iType == EMediaNotPresent)
639 test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)gDriveToTest);
641 test.Printf(_L("%c: medium found (type %d) but drive not ready\nPrevious test may have hung; else, check hardware.\n"), (TUint)gDriveToTest, (TInt)info.iType);
643 else if (r == KErrCorrupt)
645 test.Printf(_L("%c: Media corruption; previous test may have aborted; else, check hardware\n"), (TUint)gDriveToTest);
649 if(!IsFAT(TheFs, gDrive))
651 test.Printf(_L("Tests skipped on non-FAT drive\n"));
655 if ((volInfo.iDrive.iMediaAtt & KMediaAttFormattable))
658 if(CheckForDiskSize())
661 if ((volInfo.iDrive.iMediaAtt & KMediaAttFormattable))
666 test.Printf(_L("Skipping tests due to lack of space to perform them in this unit\n"));