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_fsched.cpp
23 #define __E32TEST_EXTENSION__
33 //----------------------------------------------------------------------------------------------
34 //! @SYMTestCaseID PBASE-T_FSCHED-0191
37 //! @SYMTestCaseDesc This test case is exercising the Fair Scheduling functionality added to
38 //! the File Server. There are negative and positive tests.
39 //! @SYMTestActions 0 setup the environment to execute the tests and benchmarks the time
40 //! taken to write the two files that are going to be used during the test
41 //! 1 TestReadingWhileWriting uses two threads (sync case) to write a big file/
42 //! read a small file simultaneously and verifies that the timing is correct.
43 //! Same test in the async case.
44 //! 2 TestWritingWhileWriting same test as before, but the two operations are
46 //! 3 TestTwoBigOnes does the same test as 1, but with two big files, ensuring
47 //! that the first starting is the first finishing.
48 //! 4 TestReadingWhileWritingSameFile reads a file while it is being written.
49 //! 5 TestClientDies starts a file write and kills it, then checks the integrity
51 //! 6 Finally it performs the benchmark of writing the two files again, to see
52 //! if it has been degraded during the execution
54 //! @SYMTestExpectedResults finishes if the fair scheduling behaves as expected, panics otherwise
55 //! @SYMTestPriority High
56 //! @SYMTestStatus Implemented
57 //----------------------------------------------------------------------------------------------
60 class RTestThreadSemaphore : public RSemaphore
63 inline void Signal(TInt aError = KErrNone) {iError = aError; RSemaphore::Signal();};
68 // macro to be used in place of test(). Signals main thread if assertion fails
73 if (t.Id() != gMainThreadId) \
74 client.Signal(KErrGeneral); \
77 #define TESTERROR(x) \
81 if (t.Id() != gMainThreadId) \
82 RDebug::Print(_L("error %d\n"), x); \
84 test.Printf(_L("error %d\n"), x); \
88 #define CLIENTWAIT() {client.Wait(); test(client.iError == KErrNone);}
90 ////////////////////////////////////////////////////////////
91 // Template functions encapsulating ControlIo magic
93 GLDEF_D template <class C>
94 GLDEF_C TInt controlIo(RFs &fs, TInt drv, TInt fkn, C &c)
96 TPtr8 ptrC((TUint8 *)&c, sizeof(C), sizeof(C));
98 TInt r = fs.ControlIo(drv, fkn, ptrC);
104 GLDEF_D RTest test(_L("T_FSCHED"));
108 GLDEF_D TFileName gSessionPath;
109 GLDEF_D TChar gDriveToTest;
110 TThreadId gMainThreadId;
113 TPtr8 gBufReadPtr(NULL, 0);
114 HBufC8* gBufSec = NULL;
115 TPtr8 gBufWritePtr(NULL, 0);
117 const TInt KuStomS = 1000;
118 const TInt KOneK = 1024;
119 const TInt KOneMeg = KOneK * 1024;
120 const TInt KBigBlockSize = KOneMeg ;
121 const TInt KBlockSize = KOneK * 129 ;
122 const TInt KWaitRequestsTableSize = 70;
124 TInt gBigFileSize = 0;
125 TInt gSmallFileSize = 0;
126 TInt64 gMediaSize = 0;
127 TInt gTotalTimeSync[2];
128 TInt gTotalTimeAsync[2];
130 TTimeIntervalMicroSeconds32 gTimeTakenBigFile(0);
131 TTimeIntervalMicroSeconds32 gTimeTakenBigBlock(0);
132 TBuf16<45> gSmallFile, gBigFile;
139 // Concurrent Threads
142 RTestThreadSemaphore client;
143 const TInt KHeapSize = 0x4000;
144 const TInt KMaxHeapSize = 0x200000;
145 TRequestStatus gStatus[KWaitRequestsTableSize];
154 /** Generates a file name of the form FFFFF*<aPos>.TXT (aLong.3)
156 @param aBuffer The filename will be returned here
157 @param aLong Defines the longitude of the file name
158 @param aPos Defines the number that will be attached to the filename
160 void FileNameGen(TDes16& aBuffer, TInt aLong, TInt aPos)
167 tempbuf.Format(KNumber,aPos);
168 padding=aLong-tempbuf.Size()/2;
175 aBuffer.Append(tempbuf);
177 _LIT(KExtension1, ".TXT");
178 aBuffer.Append(KExtension1);
182 /** Reads the parameters from the comand line
183 and updates the appropriate variables
185 void parseCommandLine()
188 User::CommandLine(cmd);
190 TPtrC token=lex.NextToken();
193 if(token.Length()!=0)
195 gDriveToTest = token[0];
196 gDriveToTest.UpperCase();
203 r = TheFs.CharToDrive(gDriveToTest,gDrive);
205 gSessionPath = _L("?:\\F32-TST\\");
206 gSessionPath[0] = (TText)(gDrive+'A');
207 test.Printf(_L("\nCLP=%C\n"), (TInt)gDriveToTest);
210 /** Verifies the content of a buffer (all the letters are like the first one)
212 @param aBuffer Buffer to be verified
214 @return KErrNone if all the letters are the same, KErrCorrupt otherwise
216 TInt VerifyBuffer(TDes8& aBuffer, TChar aExpectedChar)
218 TChar c = aExpectedChar;
220 for(TInt i = 1; i<aBuffer.Length(); i++)
222 if(c != (TChar)(aBuffer[i]))
224 RDebug::Print(_L("VerifyBuffer() failed at +%d, %02X != %02X"), i, (TInt) c, aBuffer[i] );
232 /** Fills a buffer with character aC
234 @param aBuffer Buffer to be filled, output
235 @param aLength Length to be filled
236 @param aC Character to be used to fill the buffer
238 void FillBuffer(TDes8& aBuffer, TInt aLength, TChar aC)
240 test (aBuffer.MaxLength() >= aLength);
241 for(TInt i=0; i<aLength; i++)
247 /** Waits for all the TRequestStatus in status[] to complete
249 @param status Array of TRequestStatus
250 @param aLength Length to be filled
251 @param aC Character to be used to fill the buffer
253 void WaitForAll(TRequestStatus* status, TInt aFileSize, TInt aBlockSize)
258 if((aFileSize % aBlockSize) == 0 )
259 size = aFileSize/aBlockSize;
261 size = (aFileSize/aBlockSize) + 1;
265 User::WaitForRequest(status[i++]);
269 /** Writes a file synchronously in blocks of aBlockSize size
272 @param aFile File name
273 @param aSize Size of the file in bytes
274 @param aBlockSize Size of the blocks to be used in bytes
275 @param aState Determines if the operation is being done in the main process
278 @return Returns KErrNone if everything ok, otherwise it panics
280 TInt WriteFile(RFs& fs, TDes16& aFile, TInt aSize, TInt aBlockSize, TTestState aState)
287 r = fileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite|EFileWriteDirectIO);
290 if(aState==EThreadWait)
293 User::After(gTimeTakenBigBlock);
299 if((j == 0) && (aState == EThreadSignal))
304 if((aSize - j) >= aBlockSize) // All the blocks but the last one
305 r = fileWrite.Write(gBufWritePtr, aBlockSize);
306 else // The last block
307 r = fileWrite.Write(gBufWritePtr, (aSize - j));
318 /** Read File in blocks of size aBlockSize
321 @param aFile File name
322 @param aBlockSize Size of the blocks to be used in bytes
323 @param aState Determines if the operation is being done in the main process
326 @return Returns KErrNone if everything ok, otherwise it panics
328 TInt ReadFile(RFs& fs, TDes16& aFile, TInt aBlockSize, TTestState aState)
330 RTest test(_L("T_FSCHED"));
331 TInt r = 0, size = 0;
334 TEST(aBlockSize > 0);
336 r = fileRead.Open(fs, aFile, EFileShareAny|EFileRead|EFileReadDirectIO);
339 r = fileRead.Size(size);
342 if(aState == EThreadWait)
345 User::After(gTimeTakenBigBlock);
351 if((j == 0)&&(aState == EThreadSignal))
355 r = fileRead.Read(gBufReadPtr, aBlockSize);
357 r = VerifyBuffer(gBufReadPtr, 'B');
361 r = fileRead.Size(size);
371 /** Write a file asynchronously in blocks of aBlockSize size
374 @param aFileWrite RFile object, needs to exist beyond the scope of this function
375 @param aFile File name
376 @param aSize Size of the file in bytes
377 @param aBlockSize Size of the blocks to be used in bytes
378 @param aStatus TRequestStatus array for all the requests
380 void WriteFileAsync(RFs& fs, RFile& aFileWrite, TDes16& aFile, TInt aSize, TInt aBlockSize, TRequestStatus aStatus[])
385 TEST(aBlockSize > 0); // Block size must be greater than 0
387 r = aFileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite|EFileWriteDirectIO);
394 if((aSize - j) >= aBlockSize) // All the blocks but the last one
395 aFileWrite.Write(gBufWritePtr, aBlockSize, aStatus[i]);
396 else // The last block
397 aFileWrite.Write(gBufWritePtr, (aSize - j), aStatus[i]);
399 TInt status = aStatus[i].Int();
400 if (status != KErrNone && status != KRequestPending)
402 test.Printf(_L("RFile::Write() returned %d\n"), aStatus[i].Int());
405 test (status == KErrNone || status == KRequestPending);
411 /** Read a file asynchronously in blocks of aBlockSize size
414 @param aFileRead RFile object, needs to exist beyond the scope of this function
415 @param aFile File name
416 @param aSize Size of the file in bytes
417 @param aBlockSize Size of the blocks to be used in bytes
418 @param aStatus TRequestStatus array for all the requests
422 TInt ReadFileAsync(RFs& fs, RFile& aFileRead, TDes16& aFile, TInt aBlockSize, TRequestStatus aStatus[])
424 TInt r = 0, size = 0;
426 TEST(aBlockSize > 0); // Block size must be greater than 0
429 r = aFileRead.Open(fs, aFile, EFileShareAny|EFileRead|EFileReadDirectIO);
432 r = aFileRead.Size(size);
438 aFileRead.Read(gBufReadPtr, aBlockSize, aStatus[i]);
439 test (aStatus[i].Int() == KErrNone || aStatus[i].Int() == KRequestPending);
450 Write a pattern to 2 files simultaneously in blocks of aBlockSize size and verify that fair scheduling
451 does not interfere with the write order by reading both files back and verifying the contents.
453 aBlockSize should be slightly bigger that the fair scheduling size
455 @param aFs RFs object
456 @param aSize Size of the file in bytes
457 @param aBlockSize Size of the blocks to be used in bytes, should be slightly bigger that the fair scheduling size
459 void WriteOrderTest(RFs& aFs, TInt aSize, TInt aBlockSize)
461 TFileName fileName1, fileName2;
462 FileNameGen(fileName1, 8, 99);
463 FileNameGen(fileName2, 8, 100);
467 TRequestStatus status1[KWaitRequestsTableSize];
468 TRequestStatus status2[KWaitRequestsTableSize];
472 TEST(aBlockSize > 0); // Block size must be greater than 0
474 r = file1.Replace(aFs, fileName1,EFileShareAny|EFileWrite|EFileWriteDirectIO);
477 r = file2.Replace(aFs, fileName2,EFileShareAny|EFileWrite|EFileWriteDirectIO);
482 TRAP(r,buf1 = HBufC8::NewL(KBigBlockSize));
483 TEST(r == KErrNone && buf1 != NULL);
485 TInt maxBlockNum = KBigBlockSize / aBlockSize;
487 TInt blocksFree = maxBlockNum;
489 TInt blockHead = 0; // ha ha
493 TPtrC8* writeBuffer = new TPtrC8[maxBlockNum];
494 for (TInt n=0; n<maxBlockNum; n++)
496 TUint8* addr = (TUint8*) buf1->Des().Ptr() + (n * aBlockSize);
497 writeBuffer[n].Set(addr, aBlockSize);
505 // fill the buffer with a char based on the block number
506 TPtr8 bufWritePtr((TUint8*) writeBuffer[blockHead].Ptr(), 0, writeBuffer[blockHead].Length());
507 TUint8* addr = (TUint8*) buf1->Des().Ptr() + (blockHead * aBlockSize);
508 bufWritePtr.Set(addr, 0, aBlockSize);
509 FillBuffer(bufWritePtr, aBlockSize, 'A'+blockNum);
511 //test.Printf(_L("j %d, addr %08X, aSize %d, blockNum %d, blockTail %d, blockHead %d, maxBlockNum %d, blocksFree %d\n"),
512 // j, writeBuffer[blockHead].Ptr(), aSize, blockNum, blockTail, blockHead, maxBlockNum, blocksFree);
514 if((aSize - j) >= aBlockSize) // All the blocks but the last one
515 file1.Write(writeBuffer[blockHead], aBlockSize, status1[blockHead]);
516 else // The last block
517 file1.Write(writeBuffer[blockHead], (aSize - j), status1[blockHead]);
519 if((aSize - j) >= aBlockSize) // All the blocks but the last one
520 file2.Write(writeBuffer[blockHead], aBlockSize, status2[blockHead]);
521 else // The last block
522 file2.Write(writeBuffer[blockHead], (aSize - j), status2[blockHead]);
524 TInt status = status1[blockHead].Int();
525 if (status != KErrNone && status != KRequestPending)
526 test.Printf(_L("RFile::Write() returned %d\n"), status1[blockHead].Int());
527 test (status == KErrNone || status == KRequestPending);
529 status = status2[blockHead].Int();
530 if (status != KErrNone && status != KRequestPending)
531 test.Printf(_L("RFile::Write() returned %d\n"), status1[blockHead].Int());
532 test (status == KErrNone || status == KRequestPending);
537 blockHead = (blockHead + 1) % maxBlockNum;
542 //test.Printf(_L("Waiting for block %d\n"), blockTail);
543 User::WaitForRequest(status1[blockTail]);
544 User::WaitForRequest(status2[blockTail]);
545 blockTail = (blockTail + 1) % maxBlockNum;
551 while (blockTail != blockHead)
553 //test.Printf(_L("Waiting for block %d\n"), blockTail);
554 User::WaitForRequest(status1[blockTail]);
555 User::WaitForRequest(status2[blockTail]);
556 blockTail = (blockTail + 1) % maxBlockNum;
564 r = file1.Open(aFs, fileName1, EFileShareAny|EFileRead|EFileReadDirectIO);
567 r = file1.Size(size);
573 TPtr8 readPtr((TUint8*) writeBuffer[0].Ptr(), aBlockSize, aBlockSize);
574 r = file1.Read(readPtr);
576 r = VerifyBuffer(readPtr, 'A' + blockNum);
583 r = file2.Open(aFs, fileName2, EFileShareAny|EFileRead|EFileReadDirectIO);
585 r = file2.Size(size);
591 TPtr8 readPtr((TUint8*) writeBuffer[0].Ptr(), aBlockSize, aBlockSize);
592 r = file2.Read(readPtr);
594 r = VerifyBuffer(readPtr, 'A' + blockNum);
603 delete [] writeBuffer;
606 r = aFs.Delete(fileName1);
608 r = aFs.Delete(fileName2);
614 /** Measure the time taken for a big block to be written synchronously
616 void TimeTakenToWriteBigBlock()
622 TInt r = fileWrite.Replace(TheFs,gBigFile,EFileShareAny|EFileWrite|EFileWriteDirectIO);
625 // Calculate how long it takes to write a big block to be able to issue at the right time the concurrent writes
626 startTime.HomeTime();
628 r = fileWrite.Write(gBufWritePtr, KBigBlockSize);
636 gTimeTakenBigBlock = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()/3);
638 test.Printf(_L("\nTime spent to write the big block in isolation: %d ms\n"), gTimeTakenBigBlock.Int() / KuStomS);
642 /** Measure the time taken for this file to be written synchronously
644 void TimeTakenToWriteBigFile(TInt aPos)
649 test((aPos >= 0) && (aPos <= 1));
650 startTime.HomeTime();
652 WriteFile(TheFs,gBigFile, gBigFileSize, KBigBlockSize, ENoThreads);
656 gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
659 test.Printf(_L("\nTime spent to write the big file in isolation: %d ms\n"), gTimeTakenBigFile.Int() / KuStomS);
661 gTotalTimeSync[aPos] = Max((gTimeTakenBigFile.Int()/KuStomS), gTotalTimeSync[aPos]) ;
664 /** Measure the time taken for this file to be written asynchronously
666 void TimeTakenToWriteBigFileAsync(TInt aPos)
671 TRequestStatus status[KWaitRequestsTableSize];
674 test((aPos >= 0) && (aPos <= 1));
676 startTime.HomeTime();
677 WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize,KBigBlockSize,status);
681 WaitForAll(status, gBigFileSize, KBigBlockSize);
685 gTimeTakenBigFile=I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
687 test.Printf(_L("\nTime to queue the blocks in isolation asynchronously: %d ms, "), gTimeTakenBigFile.Int() / KuStomS);
688 gTimeTakenBigFile=I64LOW(endTime2.MicroSecondsFrom(startTime).Int64());
689 test.Printf(_L("to actually write it: %d ms\n"),gTimeTakenBigFile.Int() / KuStomS);
690 gTotalTimeAsync[aPos] = Max((gTimeTakenBigFile.Int() / KuStomS), gTotalTimeAsync[aPos]) ;
693 /** Delete content of directory
695 @param aDir Target directory
697 @return Error returned if any, otherwise KErrNone
699 TInt DeleteAll(TDes16& aDir)
702 CFileMan* fMan=CFileMan::NewL(TheFs);
706 dir.Append(_L("F*.*"));
707 r = fMan->Delete(dir);
713 /** Read a small file sync, in a different thread
717 TInt ReadSmallFile(TAny* )
719 RTest test(_L("T_FSCHED"));
724 r = fs.SetSessionPath(gSessionPath);
727 ReadFile(fs,gSmallFile,KBlockSize, EThreadWait);
738 /** Read the big file sync, in a different thread
742 TInt ReadBigFile(TAny* )
744 RTest test(_L("T_FSCHED"));
749 r=fs.SetSessionPath(gSessionPath);
752 ReadFile(fs,gBigFile,KBlockSize, EThreadWait);
763 /** Write a small file sync, in a different thread
767 TInt WriteSmallFile(TAny* )
769 RTest test(_L("T_FSCHED"));
774 r=fs.SetSessionPath(gSessionPath);
777 WriteFile(fs,gSmallFile,gSmallFileSize, KBlockSize, EThreadWait);
788 /** Write a big file sync, in a different thread
792 TInt WriteBigFile(TAny* )
794 RTest test(_L("T_FSCHED"));
799 r=fs.SetSessionPath(gSessionPath);
802 WriteFile(fs, gBigFile, gBigFileSize, KBigBlockSize, EThreadSignal);
813 /** Write big file after a signalling thread has been scheduled, in a different thread
817 TInt WriteBigFile2(TAny* )
819 RTest test(_L("T_FSCHED"));
824 r = fs.SetSessionPath(gSessionPath);
827 WriteFile(fs, gSmallFile, gBigFileSize, KBigBlockSize, EThreadWait);
838 /** Write a big file async, in a different thread
842 TInt WriteBigFileAsync(TAny* )
844 RTest test(_L("T_FSCHED"));
846 TInt r = fs.Connect();
849 r=fs.SetSessionPath(gSessionPath);
855 WriteFileAsync(fs, bigFile, gSmallFile, gBigFileSize, KBlockSize,gStatus);
857 WaitForAll(gStatus, gBigFileSize, KBlockSize);
865 /** Delete a big file, in a different thread
869 TInt DeleteBigFile(TAny* )
871 RTest test(_L("T_FSCHED"));
873 TInt r = fs.Connect();
876 r = fs.SetSessionPath(gSessionPath);
881 r = fs.Delete(gBigFile);
882 #if defined(__WINS__)
883 TEST(r == KErrInUse || r == KErrNone);
885 test_Equal(KErrInUse, r);
896 /** Reads a small file while writing a big one
899 void TestReadingWhileWriting()
907 // Write the small file and take the appropriate measures
908 WriteFile(TheFs,gSmallFile,KBlockSize, KBlockSize, ENoThreads);
911 TBuf<20> buf=_L("Big Write");
912 r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
915 buf = _L("Small Read");
916 r = gSmall.Create(buf, ReadSmallFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
929 TTimeIntervalMicroSeconds timeTaken = gTime1.MicroSecondsFrom(gTime2);
930 test.Printf(_L("\nSync read done %d ms before the write ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
931 TReal time=I64LOW(timeTaken.Int64() / KuStomS);
932 #if !defined(__WINS__)
933 // If this condition fails, means that writing the sync file while fairscheduling a small sync read takes too long
934 test.Printf(_L("time: %f\n"), time);
935 // test((time > 0) && (((gTotalTimeSync[0]-time)>0) || ((gTotalTimeSync[1]-time)>0)) );
940 TRequestStatus status[KWaitRequestsTableSize];
941 TRequestStatus status2[2];
942 RFile bigFile, smallFile;
944 WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize ,status);
945 ReadFileAsync(TheFs, smallFile, gSmallFile, KBlockSize, status2 );
947 WaitForAll(status2,KBlockSize , KBlockSize );
950 WaitForAll(status,gBigFileSize, KBigBlockSize);
956 timeTaken = time2.MicroSecondsFrom(time1);
958 test.Printf(_L("\nAsync read done %d ms before the write ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
959 time = I64LOW(timeTaken.Int64() / KuStomS);
961 #if !defined(__WINS__)
962 // If this condition fails, means that writing the async file while fairscheduling a small async read takes too long
963 test.Printf(_L("time: %f\n"), time);
964 test.Printf(_L("gTotalTimeAsync[0] = %d , gTotalTimeAsync[1] = %d\n"),gTotalTimeAsync[0],gTotalTimeAsync[1] );
965 // test((time > 0) && (((gTotalTimeAsync[0]-time)>0) || ((gTotalTimeAsync[1]-time)>0)) );
970 /** Writes a small file while writing a big one
973 void TestWritingWhileWriting()
980 TBuf<20> buf = _L("Big Write II");
981 r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
984 buf = _L("Small Write II");
985 r = gSmall.Create(buf, WriteSmallFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
997 TTimeIntervalMicroSeconds timeTaken = gTime1.MicroSecondsFrom(gTime2);
998 test.Printf(_L("\nSync write done %d ms before the big write ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
999 TReal time=I64LOW(timeTaken.Int64() / KuStomS);
1000 #if !defined(__WINS__)
1001 // If this condition fails, means that writing the sync file while fairscheduling a small sync write takes too long
1002 test.Printf(_L("time: %f\n"), time);
1003 // test((time > 0) && (((gTotalTimeSync[0]-time)>0) || ((gTotalTimeSync[1]-time)>0)) );
1008 TRequestStatus status[KWaitRequestsTableSize];
1009 TRequestStatus status2[1];
1010 RFile bigFile, smallFile;
1012 WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize, status);
1013 WriteFileAsync(TheFs,smallFile, gSmallFile,gSmallFileSize,KBlockSize,status2);
1014 WaitForAll(status2,gSmallFileSize, KBlockSize);
1016 WaitForAll(status, gBigFileSize, KBigBlockSize);
1019 timeTaken = time2.MicroSecondsFrom(time1);
1020 test.Printf(_L("\nAsync write done %d ms before the big write ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
1021 time=I64LOW(timeTaken.Int64() / KuStomS);
1022 #if !defined(__WINS__)
1023 // If this condition fails, means that writing the async file while fairscheduling a small async write takes too long
1024 test.Printf(_L("time: %f\n"), time);
1025 test.Printf(_L("gTotalTimeAsync[0] = %d , gTotalTimeAsync[1] = %d\n"),gTotalTimeAsync[0],gTotalTimeAsync[1] );
1026 // test((time > 0) && (((gTotalTimeAsync[0]-time)>0) || ((gTotalTimeAsync[1]-time)>0)) );
1033 /** Writes two big files, ensuring the one that started to be written later ends the last one
1036 void TestTwoBigOnes()
1043 TBuf<20> buf = _L("Big Write IIII");
1044 r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
1045 TEST(r == KErrNone);
1047 buf = _L("Big Write The Second");
1048 r = gSmall.Create(buf, WriteBigFile2, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
1049 TEST(r == KErrNone);
1060 TTimeIntervalMicroSeconds timeTaken = gTime2.MicroSecondsFrom(gTime1);
1061 test.Printf(_L("\nSync first write ended %d ms before the second write ended (same file size)\n"),I64LOW(timeTaken.Int64() / KuStomS));
1064 TRequestStatus status[KWaitRequestsTableSize];
1065 TRequestStatus status2[KWaitRequestsTableSize];
1066 RFile bigFile, bigFile2;
1068 WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize, status);
1069 WriteFileAsync(TheFs, bigFile2, gSmallFile, gBigFileSize, KBigBlockSize, status2);
1070 WaitForAll(status, gBigFileSize, KBigBlockSize);
1072 WaitForAll(status2, gBigFileSize, KBigBlockSize);
1075 timeTaken = time2.MicroSecondsFrom(time1);
1076 test.Printf(_L("\nAsync first write ended %d ms before the second write ended (same file size)\n"),I64LOW(timeTaken.Int64() / KuStomS));
1081 /** Reads the file that is being written
1084 void TestReadingWhileWritingSameFile()
1092 TBuf<20> buf = _L("Big Write IV");
1093 r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
1094 TEST(r == KErrNone);
1096 buf = _L("Read IV");
1097 r = gSmall.Create(buf, ReadBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
1098 TEST(r == KErrNone);
1106 CLOSE_AND_WAIT(gBig);
1107 CLOSE_AND_WAIT(gSmall);
1109 TTimeIntervalMicroSeconds timeTaken = gTime2.MicroSecondsFrom(gTime1);
1110 test.Printf(_L("\nSync write finished %d ms before the read ended\n"),I64LOW(timeTaken.Int64() / KuStomS));
1114 /** Client dying uncleanly before the operation is finished
1117 void TestClientDies()
1122 TBuf<20> drive = _L("?:\\");
1123 TVolumeInfo volInfo;
1124 drive[0]=(TText)(gDrive+'A');
1126 r = TheFs.CheckDisk(drive);
1127 TEST(r == KErrNone || r == KErrNotSupported);
1130 TBuf<20> buf = _L("Big Write V");
1131 r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
1132 TEST(r == KErrNone);
1134 TRequestStatus status;
1139 // Kill the writing thread and wait for it to die.
1141 if(status.Int() == KRequestPending)
1142 {// the people who wrote this test did not consider the case when the file write finishes before they try to kill the thread.
1143 gBig.Kill(KErrGeneral);
1144 User::WaitForRequest(status);
1145 TEST(gBig.ExitReason() == KErrGeneral);
1146 TEST(gBig.ExitType() == EExitKill);
1150 // Make sure the thread is destroyed and the handles it owned and IPCs
1151 // it executed are closed/cancelled.
1152 CLOSE_AND_WAIT(gBig);
1155 r = TheFs.Volume(volInfo, gDrive);
1158 r = TheFs.CheckDisk(drive);
1159 TEST(r == KErrNone || r == KErrNotSupported);
1161 r = TheFs.ScanDrive(drive);
1162 TEST(r == KErrNone || r == KErrNotSupported);
1164 test.Printf(_L("Sync operation stopped\n"));
1167 buf = _L("Big Write VI");
1168 r = gSmall.Create(buf, WriteBigFileAsync, KDefaultStackSize * 2, KHeapSize, KMaxHeapSize, NULL);
1169 TEST(r == KErrNone);
1171 gSmall.Logon(status);
1176 if(status.Int() == KRequestPending)
1178 // Kill the writing thread and wait for it to die.
1179 gSmall.Kill(KErrGeneral);
1180 User::WaitForRequest(status);
1181 TEST(gSmall.ExitReason() == KErrGeneral);
1182 TEST(gSmall.ExitType() == EExitKill);
1186 // Make sure the thread is destroyed and the handles it owned and IPCs
1187 // it executed are closed/cancelled.
1188 CLOSE_AND_WAIT(gSmall);
1190 r = TheFs.CheckDisk(drive);
1191 TEST(r == KErrNone || r == KErrNotSupported);
1193 r=TheFs.ScanDrive(drive);
1194 TEST(r == KErrNone || r == KErrNotSupported);
1196 test.Printf(_L("Async operation stopped\n"));
1199 /** Reads a small file while writing a big one
1202 void TestDeletionWhileWriting()
1207 TBuf<20> buf = _L("Big Write V");
1208 r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
1209 TEST(r == KErrNone);
1211 buf = _L("Deletion");
1212 r = gSmall.Create(buf, DeleteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL);
1213 TEST(r == KErrNone);
1224 test.Printf(_L("The file was properly blocked when writing sync, not deleted\n"));
1227 TRequestStatus status[KWaitRequestsTableSize];
1233 r = fs.SetSessionPath(gSessionPath);
1236 WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize, status);
1238 r = fs.Delete(gBigFile);
1239 TEST(r == KErrInUse);
1241 WaitForAll(status, gBigFileSize, KBigBlockSize);
1246 test.Printf(_L("The file was properly blocked when writing async, not deleted\n"));
1251 void TestWriteOrder()
1255 TInt r = fs.Connect();
1257 r = fs.SetSessionPath(gSessionPath);
1260 WriteOrderTest(TheFs, gBigFileSize, KBlockSize);
1266 /** Main tests function
1274 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1275 test.Printf(_L("Disabling Lock Fail simulation ...\n"));
1276 // turn OFF lock failure mode (if cache is enabled)
1278 TBool simulatelockFailureMode = EFalse;
1279 r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode);
1280 test (r == KErrNone || r == KErrNotSupported);
1283 // FileNames/File generation
1284 test.Start(_L("Preparing the environment\n"));
1286 FileNameGen(gSmallFile, 8, gNextFile++);
1287 FileNameGen(gBigFile, 8, gNextFile++);
1290 dir.Append(gSmallFile);
1294 dir.Append(gBigFile);
1297 TRAPD(res,gBuf = HBufC8::NewL(KBigBlockSize));
1298 TEST(res == KErrNone && gBuf != NULL);
1300 gBufWritePtr.Set(gBuf->Des());
1301 FillBuffer(gBufWritePtr, KBigBlockSize, 'B');
1303 TRAPD(res2, gBufSec = HBufC8::NewL(KBlockSize));
1304 TEST(res2 == KErrNone && gBufSec != NULL);
1305 gBufReadPtr.Set(gBufSec->Des());
1307 test.Next(_L("Benchmarking\n"));
1308 TimeTakenToWriteBigFile(0);
1309 TimeTakenToWriteBigFileAsync(0);
1311 test.Printf(_L("second try, second timings account for the last comparison\n"));
1312 TimeTakenToWriteBigFile(0);
1313 TimeTakenToWriteBigFileAsync(0);
1315 TimeTakenToWriteBigBlock();
1317 test.Next(_L("Big file sync written, small file read from the media at the same time\n"));
1318 TestReadingWhileWriting();
1320 test.Next(_L("Big file written, small file written at the same time\n"));
1321 TestWritingWhileWriting();
1323 test.Next(_L("Big file written async, deletion in the meantime\n"));
1324 TestDeletionWhileWriting();
1326 test.Next(_L("Two big files written at the same time\n"));
1329 test.Next(_L("Big file being written, start reading\n"));
1330 TestReadingWhileWritingSameFile();
1332 test.Next(_L("Client dying unexpectedly\n"));
1335 test.Next(_L("Ensure write order is preserved\n"));
1338 // Format the drive to make sure no blocks are left to be erased in LFFS
1339 #if !defined(__WINS__)
1342 r = TheFs.MkDirAll(gSessionPath);
1344 TimeTakenToWriteBigFile(1);
1345 TimeTakenToWriteBigFileAsync(1);
1347 // Make sure that the difference between the first time and the last time the files are written doesn't
1348 // differ more than 3%
1349 test.Printf(_L("Abs(gTotalTimeSync[0]-gTotalTimeSync[1]) :%d\n"), Abs(gTotalTimeSync[0]-gTotalTimeSync[1]));
1350 test.Printf(_L("Abs(gTotalTimeAsync[0]-gTotalTimeAsync[1]) :%d\n"), Abs(gTotalTimeAsync[0]-gTotalTimeAsync[1]));
1351 test.Printf(_L("gTotalTimeSync[0] :%d\n"), gTotalTimeSync[0]);
1352 test.Printf(_L("gTotalTimeAsync[0] :%d\n"), gTotalTimeAsync[0]);
1354 #if !defined(__WINS__)
1355 test((Abs(gTotalTimeSync[0]-gTotalTimeSync[1])/gTotalTimeSync[0]) < 0.03);
1356 test((Abs(gTotalTimeAsync[0]-gTotalTimeAsync[1])/gTotalTimeAsync[0]) < 0.03);
1359 r = DeleteAll(gSessionPath);
1365 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1366 // turn lock failure mode back ON (if cache is enabled)
1367 simulatelockFailureMode = ETrue;
1368 r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode);
1369 test (r == KErrNone || r == KErrNotSupported);
1375 /** Initialises semaphores and call the tests
1381 r = client.CreateLocal(0);
1384 r = gSync.CreateLocal(0);
1387 r = TheFs.SetSessionPath(gSessionPath);
1390 r = TheFs.MkDirAll(gSessionPath);
1391 if (r != KErrNone && r != KErrAlreadyExists)
1395 TheFs.ResourceCountMarkStart();
1396 TRAP(r,CallTestsL());
1398 TheFs.ResourceCountMarkEnd();
1405 /** Determines the space that can be used for the files
1408 TBool CheckForDiskSize()
1410 TVolumeInfo volInfo;
1411 TInt r = TheFs.Volume(volInfo, gDrive);
1414 gMediaSize = volInfo.iSize;
1415 gSmallFileSize = KBlockSize;
1416 gBigFileSize = KBlockSize*20;
1418 while(((2*gBigFileSize)+KOneMeg) > gMediaSize )
1420 gBigFileSize -= (2*KBlockSize);
1423 TReal32 small = (TReal32)(gSmallFileSize/KOneK);
1424 TReal32 big = (TReal32)(gBigFileSize/KOneK);
1427 test.Printf(_L("Small File Size: %.2f KB\n"), small);
1428 test.Printf(_L("Big File Size: %.2f KB (%.2f MB)\n"), big, big / KOneK);
1430 if(gBigFileSize< (3*gSmallFileSize))
1436 /** Formats the drive
1438 @param aDrive Drive to be formatted
1440 void Format(TInt aDrive)
1443 test.Next(_L("Format"));
1444 TBuf<4> driveBuf = _L("?:\\");
1445 driveBuf[0] = (TText)(aDrive+'A');
1447 TInt count, prevcount = 0;
1448 TInt r = format.Open(TheFs, driveBuf, EQuickFormat, count);
1453 TInt r = format.Next(count);
1454 if(count != prevcount)
1456 test.Printf(_L("."));
1467 @return KErrNone if everything was ok, panics otherwise
1472 gMainThreadId = t.Id();
1474 CTrapCleanup* cleanup;
1475 cleanup = CTrapCleanup::New();
1478 test.Start(_L("Starting tests... T_FSCHED"));
1481 TInt r = TheFs.Connect();
1485 TVolumeInfo volInfo;
1486 r = TheFs.Drive(info, gDrive);
1489 if(info.iMediaAtt&KMediaAttVariableSize)
1491 test.Printf(_L("Tests skipped in RAM drive\n"));
1495 r = TheFs.Volume(volInfo, gDrive);
1496 if (r == KErrNotReady)
1498 if (info.iType == EMediaNotPresent)
1499 test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)gDrive + 'A');
1501 test.Printf(_L("medium found (type %d) but drive %c: not ready\nPrevious test may have hung; else, check hardware.\n"), (TInt)info.iType, (TUint)gDrive + 'A');
1503 else if (r == KErrCorrupt)
1505 test.Printf(_L("%c: Media corruption; previous test may have aborted; else, check hardware\n"), (TUint)gDrive + 'A');
1508 #if !defined(__WINS__)
1509 if ((volInfo.iDrive.iMediaAtt & KMediaAttFormattable))
1513 if(CheckForDiskSize())
1519 test.Printf(_L("Skipping tests due to lack of space to perform them in this drive\n"));