sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32test\server\t_fsched.cpp sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @internalTechnology sl@0: */ sl@0: sl@0: #define __E32TEST_EXTENSION__ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "t_server.h" sl@0: #include sl@0: #include sl@0: sl@0: //---------------------------------------------------------------------------------------------- sl@0: //! @SYMTestCaseID PBASE-T_FSCHED-0191 sl@0: //! @SYMTestType CIT sl@0: //! @SYMPREQ PREQ914 sl@0: //! @SYMTestCaseDesc This test case is exercising the Fair Scheduling functionality added to sl@0: //! the File Server. There are negative and positive tests. sl@0: //! @SYMTestActions 0 setup the environment to execute the tests and benchmarks the time sl@0: //! taken to write the two files that are going to be used during the test sl@0: //! 1 TestReadingWhileWriting uses two threads (sync case) to write a big file/ sl@0: //! read a small file simultaneously and verifies that the timing is correct. sl@0: //! Same test in the async case. sl@0: //! 2 TestWritingWhileWriting same test as before, but the two operations are sl@0: //! writes. sl@0: //! 3 TestTwoBigOnes does the same test as 1, but with two big files, ensuring sl@0: //! that the first starting is the first finishing. sl@0: //! 4 TestReadingWhileWritingSameFile reads a file while it is being written. sl@0: //! 5 TestClientDies starts a file write and kills it, then checks the integrity sl@0: //! of the volume. sl@0: //! 6 Finally it performs the benchmark of writing the two files again, to see sl@0: //! if it has been degraded during the execution sl@0: //! sl@0: //! @SYMTestExpectedResults finishes if the fair scheduling behaves as expected, panics otherwise sl@0: //! @SYMTestPriority High sl@0: //! @SYMTestStatus Implemented sl@0: //---------------------------------------------------------------------------------------------- sl@0: sl@0: sl@0: class RTestThreadSemaphore : public RSemaphore sl@0: { sl@0: public: sl@0: inline void Signal(TInt aError = KErrNone) {iError = aError; RSemaphore::Signal();}; sl@0: public: sl@0: TInt iError; sl@0: }; sl@0: sl@0: // macro to be used in place of test(). Signals main thread if assertion fails sl@0: #define TEST(x) \ sl@0: if (!(x)) \ sl@0: { \ sl@0: RThread t; \ sl@0: if (t.Id() != gMainThreadId) \ sl@0: client.Signal(KErrGeneral); \ sl@0: test(x); \ sl@0: } sl@0: #define TESTERROR(x) \ sl@0: if (x != KErrNone) \ sl@0: { \ sl@0: RThread t; \ sl@0: if (t.Id() != gMainThreadId) \ sl@0: RDebug::Print(_L("error %d\n"), x); \ sl@0: else \ sl@0: test.Printf(_L("error %d\n"), x); \ sl@0: TEST(x==KErrNone); \ sl@0: } sl@0: sl@0: #define CLIENTWAIT() {client.Wait(); test(client.iError == KErrNone);} sl@0: sl@0: //////////////////////////////////////////////////////////// sl@0: // Template functions encapsulating ControlIo magic sl@0: // sl@0: GLDEF_D template sl@0: GLDEF_C TInt controlIo(RFs &fs, TInt drv, TInt fkn, C &c) sl@0: { sl@0: TPtr8 ptrC((TUint8 *)&c, sizeof(C), sizeof(C)); sl@0: sl@0: TInt r = fs.ControlIo(drv, fkn, ptrC); sl@0: sl@0: return r; sl@0: } sl@0: sl@0: sl@0: GLDEF_D RTest test(_L("T_FSCHED")); sl@0: sl@0: GLDEF_D RFs TheFs; sl@0: GLDEF_D TInt gDrive; sl@0: GLDEF_D TFileName gSessionPath; sl@0: GLDEF_D TChar gDriveToTest; sl@0: TThreadId gMainThreadId; sl@0: sl@0: HBufC8* gBuf = NULL; sl@0: TPtr8 gBufReadPtr(NULL, 0); sl@0: HBufC8* gBufSec = NULL; sl@0: TPtr8 gBufWritePtr(NULL, 0); sl@0: sl@0: const TInt KuStomS = 1000; sl@0: const TInt KOneK = 1024; sl@0: const TInt KOneMeg = KOneK * 1024; sl@0: const TInt KBigBlockSize = KOneMeg ; sl@0: const TInt KBlockSize = KOneK * 129 ; sl@0: const TInt KWaitRequestsTableSize = 70; sl@0: sl@0: TInt gBigFileSize = 0; sl@0: TInt gSmallFileSize = 0; sl@0: TInt64 gMediaSize = 0; sl@0: TInt gTotalTimeSync[2]; sl@0: TInt gTotalTimeAsync[2]; sl@0: sl@0: TTimeIntervalMicroSeconds32 gTimeTakenBigFile(0); sl@0: TTimeIntervalMicroSeconds32 gTimeTakenBigBlock(0); sl@0: TBuf16<45> gSmallFile, gBigFile; sl@0: TInt gNextFile=0; sl@0: TTime gTime1; sl@0: TTime gTime2; sl@0: sl@0: RSemaphore gSync; sl@0: sl@0: // Concurrent Threads sl@0: RThread gBig; sl@0: RThread gSmall; sl@0: RTestThreadSemaphore client; sl@0: const TInt KHeapSize = 0x4000; sl@0: const TInt KMaxHeapSize = 0x200000; sl@0: TRequestStatus gStatus[KWaitRequestsTableSize]; sl@0: sl@0: enum TTestState sl@0: { sl@0: EThreadWait, sl@0: EThreadSignal, sl@0: ENoThreads sl@0: }; sl@0: sl@0: /** Generates a file name of the form FFFFF*.TXT (aLong.3) sl@0: sl@0: @param aBuffer The filename will be returned here sl@0: @param aLong Defines the longitude of the file name sl@0: @param aPos Defines the number that will be attached to the filename sl@0: */ sl@0: void FileNameGen(TDes16& aBuffer, TInt aLong, TInt aPos) sl@0: { sl@0: TInt padding; sl@0: TInt i=0; sl@0: TBuf16<10> tempbuf; sl@0: sl@0: _LIT(KNumber,"%d"); sl@0: tempbuf.Format(KNumber,aPos); sl@0: padding=aLong-tempbuf.Size()/2; sl@0: aBuffer=_L(""); sl@0: while(i cmd; sl@0: User::CommandLine(cmd); sl@0: TLex lex(cmd); sl@0: TPtrC token=lex.NextToken(); sl@0: TInt r=0; sl@0: sl@0: if(token.Length()!=0) sl@0: { sl@0: gDriveToTest = token[0]; sl@0: gDriveToTest.UpperCase(); sl@0: } sl@0: else sl@0: { sl@0: gDriveToTest='C'; sl@0: } sl@0: sl@0: r = TheFs.CharToDrive(gDriveToTest,gDrive); sl@0: TESTERROR(r); sl@0: gSessionPath = _L("?:\\F32-TST\\"); sl@0: gSessionPath[0] = (TText)(gDrive+'A'); sl@0: test.Printf(_L("\nCLP=%C\n"), (TInt)gDriveToTest); sl@0: } sl@0: sl@0: /** Verifies the content of a buffer (all the letters are like the first one) sl@0: sl@0: @param aBuffer Buffer to be verified sl@0: sl@0: @return KErrNone if all the letters are the same, KErrCorrupt otherwise sl@0: */ sl@0: TInt VerifyBuffer(TDes8& aBuffer, TChar aExpectedChar) sl@0: { sl@0: TChar c = aExpectedChar; sl@0: sl@0: for(TInt i = 1; i= aLength); sl@0: for(TInt i=0; i0); sl@0: sl@0: r = fileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: TESTERROR(r); sl@0: sl@0: if(aState==EThreadWait) sl@0: { sl@0: gSync.Wait(); sl@0: User::After(gTimeTakenBigBlock); sl@0: } sl@0: sl@0: TInt j = 0; sl@0: while(j < aSize) sl@0: { sl@0: if((j == 0) && (aState == EThreadSignal)) sl@0: { sl@0: gSync.Signal(); sl@0: } sl@0: sl@0: if((aSize - j) >= aBlockSize) // All the blocks but the last one sl@0: r = fileWrite.Write(gBufWritePtr, aBlockSize); sl@0: else // The last block sl@0: r = fileWrite.Write(gBufWritePtr, (aSize - j)); sl@0: sl@0: TESTERROR(r); sl@0: j += aBlockSize; sl@0: } sl@0: sl@0: fileWrite.Close(); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** Read File in blocks of size aBlockSize sl@0: sl@0: @param fs RFs object sl@0: @param aFile File name sl@0: @param aBlockSize Size of the blocks to be used in bytes sl@0: @param aState Determines if the operation is being done in the main process sl@0: or in a thread sl@0: sl@0: @return Returns KErrNone if everything ok, otherwise it panics sl@0: */ sl@0: TInt ReadFile(RFs& fs, TDes16& aFile, TInt aBlockSize, TTestState aState) sl@0: { sl@0: RTest test(_L("T_FSCHED")); sl@0: TInt r = 0, size = 0; sl@0: RFile fileRead; sl@0: sl@0: TEST(aBlockSize > 0); sl@0: sl@0: r = fileRead.Open(fs, aFile, EFileShareAny|EFileRead|EFileReadDirectIO); sl@0: TESTERROR(r); sl@0: sl@0: r = fileRead.Size(size); sl@0: TESTERROR(r); sl@0: sl@0: if(aState == EThreadWait) sl@0: { sl@0: gSync.Wait(); sl@0: User::After(gTimeTakenBigBlock); sl@0: } sl@0: sl@0: TInt j = 0; sl@0: while(j < size) sl@0: { sl@0: if((j == 0)&&(aState == EThreadSignal)) sl@0: { sl@0: gSync.Signal(); sl@0: } sl@0: r = fileRead.Read(gBufReadPtr, aBlockSize); sl@0: TESTERROR(r); sl@0: r = VerifyBuffer(gBufReadPtr, 'B'); sl@0: TESTERROR(r); sl@0: sl@0: j += aBlockSize; sl@0: r = fileRead.Size(size); sl@0: TESTERROR(r); sl@0: } sl@0: sl@0: fileRead.Close(); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: /** Write a file asynchronously in blocks of aBlockSize size sl@0: sl@0: @param fs RFs object sl@0: @param aFileWrite RFile object, needs to exist beyond the scope of this function sl@0: @param aFile File name sl@0: @param aSize Size of the file in bytes sl@0: @param aBlockSize Size of the blocks to be used in bytes sl@0: @param aStatus TRequestStatus array for all the requests sl@0: */ sl@0: void WriteFileAsync(RFs& fs, RFile& aFileWrite, TDes16& aFile, TInt aSize, TInt aBlockSize, TRequestStatus aStatus[]) sl@0: { sl@0: sl@0: TInt r = 0; sl@0: sl@0: TEST(aBlockSize > 0); // Block size must be greater than 0 sl@0: sl@0: r = aFileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: TESTERROR(r); sl@0: sl@0: TInt j = 0; sl@0: TInt i = 0; sl@0: while(j < aSize) sl@0: { sl@0: if((aSize - j) >= aBlockSize) // All the blocks but the last one sl@0: aFileWrite.Write(gBufWritePtr, aBlockSize, aStatus[i]); sl@0: else // The last block sl@0: aFileWrite.Write(gBufWritePtr, (aSize - j), aStatus[i]); sl@0: sl@0: TInt status = aStatus[i].Int(); sl@0: if (status != KErrNone && status != KRequestPending) sl@0: { sl@0: test.Printf(_L("RFile::Write() returned %d\n"), aStatus[i].Int()); sl@0: } sl@0: sl@0: test (status == KErrNone || status == KRequestPending); sl@0: i++; sl@0: j += aBlockSize; sl@0: } sl@0: } sl@0: sl@0: /** Read a file asynchronously in blocks of aBlockSize size sl@0: sl@0: @param fs RFs object sl@0: @param aFileRead RFile object, needs to exist beyond the scope of this function sl@0: @param aFile File name sl@0: @param aSize Size of the file in bytes sl@0: @param aBlockSize Size of the blocks to be used in bytes sl@0: @param aStatus TRequestStatus array for all the requests sl@0: sl@0: @return KErrNone sl@0: */ sl@0: TInt ReadFileAsync(RFs& fs, RFile& aFileRead, TDes16& aFile, TInt aBlockSize, TRequestStatus aStatus[]) sl@0: { sl@0: TInt r = 0, size = 0; sl@0: sl@0: TEST(aBlockSize > 0); // Block size must be greater than 0 sl@0: sl@0: sl@0: r = aFileRead.Open(fs, aFile, EFileShareAny|EFileRead|EFileReadDirectIO); sl@0: TESTERROR(r); sl@0: sl@0: r = aFileRead.Size(size); sl@0: TESTERROR(r); sl@0: sl@0: TInt j = 0, i = 0; sl@0: while(j < size) sl@0: { sl@0: aFileRead.Read(gBufReadPtr, aBlockSize, aStatus[i]); sl@0: test (aStatus[i].Int() == KErrNone || aStatus[i].Int() == KRequestPending); sl@0: i++; sl@0: TESTERROR(r); sl@0: j += aBlockSize; sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Write a pattern to 2 files simultaneously in blocks of aBlockSize size and verify that fair scheduling sl@0: does not interfere with the write order by reading both files back and verifying the contents. sl@0: sl@0: aBlockSize should be slightly bigger that the fair scheduling size sl@0: sl@0: @param aFs RFs object sl@0: @param aSize Size of the file in bytes sl@0: @param aBlockSize Size of the blocks to be used in bytes, should be slightly bigger that the fair scheduling size sl@0: */ sl@0: void WriteOrderTest(RFs& aFs, TInt aSize, TInt aBlockSize) sl@0: { sl@0: TFileName fileName1, fileName2; sl@0: FileNameGen(fileName1, 8, 99); sl@0: FileNameGen(fileName2, 8, 100); sl@0: sl@0: RFile file1, file2; sl@0: sl@0: TRequestStatus status1[KWaitRequestsTableSize]; sl@0: TRequestStatus status2[KWaitRequestsTableSize]; sl@0: sl@0: TInt r = 0; sl@0: sl@0: TEST(aBlockSize > 0); // Block size must be greater than 0 sl@0: sl@0: r = file1.Replace(aFs, fileName1,EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: TESTERROR(r); sl@0: sl@0: r = file2.Replace(aFs, fileName2,EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: TESTERROR(r); sl@0: sl@0: sl@0: HBufC8* buf1 = NULL; sl@0: TRAP(r,buf1 = HBufC8::NewL(KBigBlockSize)); sl@0: TEST(r == KErrNone && buf1 != NULL); sl@0: sl@0: TInt maxBlockNum = KBigBlockSize / aBlockSize; sl@0: TInt blockNum = 0; sl@0: TInt blocksFree = maxBlockNum; sl@0: sl@0: TInt blockHead = 0; // ha ha sl@0: TInt blockTail = 0; sl@0: sl@0: sl@0: TPtrC8* writeBuffer = new TPtrC8[maxBlockNum]; sl@0: for (TInt n=0; nDes().Ptr() + (n * aBlockSize); sl@0: writeBuffer[n].Set(addr, aBlockSize); sl@0: } sl@0: sl@0: TInt j = 0; sl@0: TInt i = 0; sl@0: while(j < aSize) sl@0: { sl@0: sl@0: // fill the buffer with a char based on the block number sl@0: TPtr8 bufWritePtr((TUint8*) writeBuffer[blockHead].Ptr(), 0, writeBuffer[blockHead].Length()); sl@0: TUint8* addr = (TUint8*) buf1->Des().Ptr() + (blockHead * aBlockSize); sl@0: bufWritePtr.Set(addr, 0, aBlockSize); sl@0: FillBuffer(bufWritePtr, aBlockSize, 'A'+blockNum); sl@0: sl@0: //test.Printf(_L("j %d, addr %08X, aSize %d, blockNum %d, blockTail %d, blockHead %d, maxBlockNum %d, blocksFree %d\n"), sl@0: // j, writeBuffer[blockHead].Ptr(), aSize, blockNum, blockTail, blockHead, maxBlockNum, blocksFree); sl@0: sl@0: if((aSize - j) >= aBlockSize) // All the blocks but the last one sl@0: file1.Write(writeBuffer[blockHead], aBlockSize, status1[blockHead]); sl@0: else // The last block sl@0: file1.Write(writeBuffer[blockHead], (aSize - j), status1[blockHead]); sl@0: sl@0: if((aSize - j) >= aBlockSize) // All the blocks but the last one sl@0: file2.Write(writeBuffer[blockHead], aBlockSize, status2[blockHead]); sl@0: else // The last block sl@0: file2.Write(writeBuffer[blockHead], (aSize - j), status2[blockHead]); sl@0: sl@0: TInt status = status1[blockHead].Int(); sl@0: if (status != KErrNone && status != KRequestPending) sl@0: test.Printf(_L("RFile::Write() returned %d\n"), status1[blockHead].Int()); sl@0: test (status == KErrNone || status == KRequestPending); sl@0: sl@0: status = status2[blockHead].Int(); sl@0: if (status != KErrNone && status != KRequestPending) sl@0: test.Printf(_L("RFile::Write() returned %d\n"), status1[blockHead].Int()); sl@0: test (status == KErrNone || status == KRequestPending); sl@0: sl@0: i++; sl@0: j += aBlockSize; sl@0: blockNum++; sl@0: blockHead = (blockHead + 1) % maxBlockNum; sl@0: blocksFree--; sl@0: sl@0: if (blocksFree == 0) sl@0: { sl@0: //test.Printf(_L("Waiting for block %d\n"), blockTail); sl@0: User::WaitForRequest(status1[blockTail]); sl@0: User::WaitForRequest(status2[blockTail]); sl@0: blockTail = (blockTail + 1) % maxBlockNum; sl@0: blocksFree++; sl@0: } sl@0: sl@0: } sl@0: sl@0: while (blockTail != blockHead) sl@0: { sl@0: //test.Printf(_L("Waiting for block %d\n"), blockTail); sl@0: User::WaitForRequest(status1[blockTail]); sl@0: User::WaitForRequest(status2[blockTail]); sl@0: blockTail = (blockTail + 1) % maxBlockNum; sl@0: blocksFree++; sl@0: } sl@0: sl@0: file1.Close(); sl@0: file2.Close(); sl@0: sl@0: // Verify file1 sl@0: r = file1.Open(aFs, fileName1, EFileShareAny|EFileRead|EFileReadDirectIO); sl@0: TESTERROR(r); sl@0: TInt size; sl@0: r = file1.Size(size); sl@0: TESTERROR(r); sl@0: blockNum = 0; sl@0: j = 0; sl@0: while(j < size) sl@0: { sl@0: TPtr8 readPtr((TUint8*) writeBuffer[0].Ptr(), aBlockSize, aBlockSize); sl@0: r = file1.Read(readPtr); sl@0: TESTERROR(r); sl@0: r = VerifyBuffer(readPtr, 'A' + blockNum); sl@0: TESTERROR(r); sl@0: j += aBlockSize; sl@0: blockNum++; sl@0: } sl@0: sl@0: // Verify file2 sl@0: r = file2.Open(aFs, fileName2, EFileShareAny|EFileRead|EFileReadDirectIO); sl@0: TESTERROR(r); sl@0: r = file2.Size(size); sl@0: TESTERROR(r); sl@0: blockNum = 0; sl@0: j = 0; sl@0: while(j < size) sl@0: { sl@0: TPtr8 readPtr((TUint8*) writeBuffer[0].Ptr(), aBlockSize, aBlockSize); sl@0: r = file2.Read(readPtr); sl@0: TESTERROR(r); sl@0: r = VerifyBuffer(readPtr, 'A' + blockNum); sl@0: TESTERROR(r); sl@0: j += aBlockSize; sl@0: blockNum++; sl@0: } sl@0: sl@0: file2.Close(); sl@0: file1.Close(); sl@0: sl@0: delete [] writeBuffer; sl@0: delete buf1; sl@0: sl@0: r = aFs.Delete(fileName1); sl@0: TEST(r == KErrNone); sl@0: r = aFs.Delete(fileName2); sl@0: TEST(r == KErrNone); sl@0: } sl@0: sl@0: sl@0: sl@0: /** Measure the time taken for a big block to be written synchronously sl@0: */ sl@0: void TimeTakenToWriteBigBlock() sl@0: { sl@0: TTime startTime; sl@0: TTime endTime; sl@0: RFile fileWrite; sl@0: sl@0: TInt r = fileWrite.Replace(TheFs,gBigFile,EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: TESTERROR(r); sl@0: sl@0: // Calculate how long it takes to write a big block to be able to issue at the right time the concurrent writes sl@0: startTime.HomeTime(); sl@0: sl@0: r = fileWrite.Write(gBufWritePtr, KBigBlockSize); sl@0: sl@0: endTime.HomeTime(); sl@0: sl@0: fileWrite.Close(); sl@0: sl@0: TESTERROR(r); sl@0: sl@0: gTimeTakenBigBlock = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()/3); sl@0: sl@0: test.Printf(_L("\nTime spent to write the big block in isolation: %d ms\n"), gTimeTakenBigBlock.Int() / KuStomS); sl@0: } sl@0: sl@0: sl@0: /** Measure the time taken for this file to be written synchronously sl@0: */ sl@0: void TimeTakenToWriteBigFile(TInt aPos) sl@0: { sl@0: TTime startTime; sl@0: TTime endTime; sl@0: sl@0: test((aPos >= 0) && (aPos <= 1)); sl@0: startTime.HomeTime(); sl@0: sl@0: WriteFile(TheFs,gBigFile, gBigFileSize, KBigBlockSize, ENoThreads); sl@0: sl@0: endTime.HomeTime(); sl@0: sl@0: gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()); sl@0: sl@0: sl@0: test.Printf(_L("\nTime spent to write the big file in isolation: %d ms\n"), gTimeTakenBigFile.Int() / KuStomS); sl@0: sl@0: gTotalTimeSync[aPos] = Max((gTimeTakenBigFile.Int()/KuStomS), gTotalTimeSync[aPos]) ; sl@0: } sl@0: sl@0: /** Measure the time taken for this file to be written asynchronously sl@0: */ sl@0: void TimeTakenToWriteBigFileAsync(TInt aPos) sl@0: { sl@0: TTime startTime; sl@0: TTime endTime; sl@0: TTime endTime2; sl@0: TRequestStatus status[KWaitRequestsTableSize]; sl@0: RFile bigFile; sl@0: sl@0: test((aPos >= 0) && (aPos <= 1)); sl@0: sl@0: startTime.HomeTime(); sl@0: WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize,KBigBlockSize,status); sl@0: endTime.HomeTime(); sl@0: sl@0: sl@0: WaitForAll(status, gBigFileSize, KBigBlockSize); sl@0: sl@0: endTime2.HomeTime(); sl@0: sl@0: gTimeTakenBigFile=I64LOW(endTime.MicroSecondsFrom(startTime).Int64()); sl@0: bigFile.Close(); sl@0: test.Printf(_L("\nTime to queue the blocks in isolation asynchronously: %d ms, "), gTimeTakenBigFile.Int() / KuStomS); sl@0: gTimeTakenBigFile=I64LOW(endTime2.MicroSecondsFrom(startTime).Int64()); sl@0: test.Printf(_L("to actually write it: %d ms\n"),gTimeTakenBigFile.Int() / KuStomS); sl@0: gTotalTimeAsync[aPos] = Max((gTimeTakenBigFile.Int() / KuStomS), gTotalTimeAsync[aPos]) ; sl@0: } sl@0: sl@0: /** Delete content of directory sl@0: sl@0: @param aDir Target directory sl@0: sl@0: @return Error returned if any, otherwise KErrNone sl@0: */ sl@0: TInt DeleteAll(TDes16& aDir) sl@0: { sl@0: TBuf16<100> dir; sl@0: CFileMan* fMan=CFileMan::NewL(TheFs); sl@0: TInt r=0; sl@0: sl@0: dir = aDir; sl@0: dir.Append(_L("F*.*")); sl@0: r = fMan->Delete(dir); sl@0: sl@0: delete fMan; sl@0: return r; sl@0: } sl@0: sl@0: /** Read a small file sync, in a different thread sl@0: sl@0: @return ETrue sl@0: */ sl@0: TInt ReadSmallFile(TAny* ) sl@0: { sl@0: RTest test(_L("T_FSCHED")); sl@0: RFs fs; sl@0: TInt r=fs.Connect(); sl@0: TESTERROR(r); sl@0: sl@0: r = fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: ReadFile(fs,gSmallFile,KBlockSize, EThreadWait); sl@0: gTime2.HomeTime(); sl@0: sl@0: client.Signal(); sl@0: sl@0: fs.Close(); sl@0: test.Close(); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: /** Read the big file sync, in a different thread sl@0: sl@0: @return ETrue sl@0: */ sl@0: TInt ReadBigFile(TAny* ) sl@0: { sl@0: RTest test(_L("T_FSCHED")); sl@0: RFs fs; sl@0: TInt r=fs.Connect(); sl@0: TESTERROR(r); sl@0: sl@0: r=fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: ReadFile(fs,gBigFile,KBlockSize, EThreadWait); sl@0: gTime2.HomeTime(); sl@0: sl@0: client.Signal(); sl@0: sl@0: fs.Close(); sl@0: test.Close(); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: /** Write a small file sync, in a different thread sl@0: sl@0: @return ETrue sl@0: */ sl@0: TInt WriteSmallFile(TAny* ) sl@0: { sl@0: RTest test(_L("T_FSCHED")); sl@0: RFs fs; sl@0: TInt r=fs.Connect(); sl@0: TESTERROR(r); sl@0: sl@0: r=fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: WriteFile(fs,gSmallFile,gSmallFileSize, KBlockSize, EThreadWait); sl@0: gTime2.HomeTime(); sl@0: sl@0: client.Signal(); sl@0: sl@0: fs.Close(); sl@0: test.Close(); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: /** Write a big file sync, in a different thread sl@0: sl@0: @return ETrue sl@0: */ sl@0: TInt WriteBigFile(TAny* ) sl@0: { sl@0: RTest test(_L("T_FSCHED")); sl@0: RFs fs; sl@0: TInt r=fs.Connect(); sl@0: TESTERROR(r); sl@0: sl@0: r=fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: WriteFile(fs, gBigFile, gBigFileSize, KBigBlockSize, EThreadSignal); sl@0: gTime1.HomeTime(); sl@0: sl@0: client.Signal(); sl@0: sl@0: fs.Close(); sl@0: test.Close(); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: /** Write big file after a signalling thread has been scheduled, in a different thread sl@0: sl@0: @return ETrue sl@0: */ sl@0: TInt WriteBigFile2(TAny* ) sl@0: { sl@0: RTest test(_L("T_FSCHED")); sl@0: RFs fs; sl@0: TInt r=fs.Connect(); sl@0: TESTERROR(r); sl@0: sl@0: r = fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: WriteFile(fs, gSmallFile, gBigFileSize, KBigBlockSize, EThreadWait); sl@0: gTime2.HomeTime(); sl@0: sl@0: client.Signal(); sl@0: sl@0: fs.Close(); sl@0: test.Close(); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: /** Write a big file async, in a different thread sl@0: sl@0: @return ETrue sl@0: */ sl@0: TInt WriteBigFileAsync(TAny* ) sl@0: { sl@0: RTest test(_L("T_FSCHED")); sl@0: RFs fs; sl@0: TInt r = fs.Connect(); sl@0: TESTERROR(r); sl@0: sl@0: r=fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: sl@0: RFile bigFile; sl@0: sl@0: WriteFileAsync(fs, bigFile, gSmallFile, gBigFileSize, KBlockSize,gStatus); sl@0: gSync.Signal(); sl@0: WaitForAll(gStatus, gBigFileSize, KBlockSize); sl@0: sl@0: fs.Close(); sl@0: test.Close(); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: /** Delete a big file, in a different thread sl@0: sl@0: @return ETrue sl@0: */ sl@0: TInt DeleteBigFile(TAny* ) sl@0: { sl@0: RTest test(_L("T_FSCHED")); sl@0: RFs fs; sl@0: TInt r = fs.Connect(); sl@0: TESTERROR(r); sl@0: sl@0: r = fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: gSync.Wait(); sl@0: sl@0: r = fs.Delete(gBigFile); sl@0: #if defined(__WINS__) sl@0: TEST(r == KErrInUse || r == KErrNone); sl@0: #else sl@0: test_Equal(KErrInUse, r); sl@0: #endif sl@0: sl@0: client.Signal(); sl@0: sl@0: fs.Close(); sl@0: test.Close(); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: /** Reads a small file while writing a big one sl@0: sl@0: */ sl@0: void TestReadingWhileWriting() sl@0: { sl@0: TInt r = 0; sl@0: TTime time1; sl@0: TTime time2; sl@0: sl@0: time1.HomeTime(); sl@0: sl@0: // Write the small file and take the appropriate measures sl@0: WriteFile(TheFs,gSmallFile,KBlockSize, KBlockSize, ENoThreads); sl@0: sl@0: // Sync test sl@0: TBuf<20> buf=_L("Big Write"); sl@0: r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: buf = _L("Small Read"); sl@0: r = gSmall.Create(buf, ReadSmallFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: gBig.Resume(); sl@0: gSmall.Resume(); sl@0: sl@0: CLIENTWAIT(); sl@0: CLIENTWAIT(); sl@0: sl@0: gBig.Close(); sl@0: gSmall.Close(); sl@0: sl@0: sl@0: TTimeIntervalMicroSeconds timeTaken = gTime1.MicroSecondsFrom(gTime2); sl@0: test.Printf(_L("\nSync read done %d ms before the write ended\n"),I64LOW(timeTaken.Int64() / KuStomS)); sl@0: TReal time=I64LOW(timeTaken.Int64() / KuStomS); sl@0: #if !defined(__WINS__) sl@0: // If this condition fails, means that writing the sync file while fairscheduling a small sync read takes too long sl@0: test.Printf(_L("time: %f\n"), time); sl@0: // test((time > 0) && (((gTotalTimeSync[0]-time)>0) || ((gTotalTimeSync[1]-time)>0)) ); sl@0: test(time > 0); sl@0: #endif sl@0: sl@0: // Async test sl@0: TRequestStatus status[KWaitRequestsTableSize]; sl@0: TRequestStatus status2[2]; sl@0: RFile bigFile, smallFile; sl@0: sl@0: WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize ,status); sl@0: ReadFileAsync(TheFs, smallFile, gSmallFile, KBlockSize, status2 ); sl@0: sl@0: WaitForAll(status2,KBlockSize , KBlockSize ); sl@0: time1.HomeTime(); sl@0: sl@0: WaitForAll(status,gBigFileSize, KBigBlockSize); sl@0: sl@0: time2.HomeTime(); sl@0: bigFile.Close(); sl@0: smallFile.Close(); sl@0: sl@0: timeTaken = time2.MicroSecondsFrom(time1); sl@0: sl@0: test.Printf(_L("\nAsync read done %d ms before the write ended\n"),I64LOW(timeTaken.Int64() / KuStomS)); sl@0: time = I64LOW(timeTaken.Int64() / KuStomS); sl@0: sl@0: #if !defined(__WINS__) sl@0: // If this condition fails, means that writing the async file while fairscheduling a small async read takes too long sl@0: test.Printf(_L("time: %f\n"), time); sl@0: test.Printf(_L("gTotalTimeAsync[0] = %d , gTotalTimeAsync[1] = %d\n"),gTotalTimeAsync[0],gTotalTimeAsync[1] ); sl@0: // test((time > 0) && (((gTotalTimeAsync[0]-time)>0) || ((gTotalTimeAsync[1]-time)>0)) ); sl@0: test(time > 0); sl@0: #endif sl@0: } sl@0: sl@0: /** Writes a small file while writing a big one sl@0: sl@0: */ sl@0: void TestWritingWhileWriting() sl@0: { sl@0: TInt r = 0; sl@0: TTime time1; sl@0: TTime time2; sl@0: sl@0: // Sync test sl@0: TBuf<20> buf = _L("Big Write II"); sl@0: r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: buf = _L("Small Write II"); sl@0: r = gSmall.Create(buf, WriteSmallFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r==KErrNone); sl@0: sl@0: gBig.Resume(); sl@0: gSmall.Resume(); sl@0: sl@0: CLIENTWAIT(); sl@0: CLIENTWAIT(); sl@0: sl@0: gBig.Close(); sl@0: gSmall.Close(); sl@0: sl@0: TTimeIntervalMicroSeconds timeTaken = gTime1.MicroSecondsFrom(gTime2); sl@0: test.Printf(_L("\nSync write done %d ms before the big write ended\n"),I64LOW(timeTaken.Int64() / KuStomS)); sl@0: TReal time=I64LOW(timeTaken.Int64() / KuStomS); sl@0: #if !defined(__WINS__) sl@0: // If this condition fails, means that writing the sync file while fairscheduling a small sync write takes too long sl@0: test.Printf(_L("time: %f\n"), time); sl@0: // test((time > 0) && (((gTotalTimeSync[0]-time)>0) || ((gTotalTimeSync[1]-time)>0)) ); sl@0: test(time > 0); sl@0: #endif sl@0: sl@0: // Async test sl@0: TRequestStatus status[KWaitRequestsTableSize]; sl@0: TRequestStatus status2[1]; sl@0: RFile bigFile, smallFile; sl@0: sl@0: WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize, status); sl@0: WriteFileAsync(TheFs,smallFile, gSmallFile,gSmallFileSize,KBlockSize,status2); sl@0: WaitForAll(status2,gSmallFileSize, KBlockSize); sl@0: time1.HomeTime(); sl@0: WaitForAll(status, gBigFileSize, KBigBlockSize); sl@0: time2.HomeTime(); sl@0: sl@0: timeTaken = time2.MicroSecondsFrom(time1); sl@0: test.Printf(_L("\nAsync write done %d ms before the big write ended\n"),I64LOW(timeTaken.Int64() / KuStomS)); sl@0: time=I64LOW(timeTaken.Int64() / KuStomS); sl@0: #if !defined(__WINS__) sl@0: // If this condition fails, means that writing the async file while fairscheduling a small async write takes too long sl@0: test.Printf(_L("time: %f\n"), time); sl@0: test.Printf(_L("gTotalTimeAsync[0] = %d , gTotalTimeAsync[1] = %d\n"),gTotalTimeAsync[0],gTotalTimeAsync[1] ); sl@0: // test((time > 0) && (((gTotalTimeAsync[0]-time)>0) || ((gTotalTimeAsync[1]-time)>0)) ); sl@0: test(time > 0); sl@0: #endif sl@0: bigFile.Close(); sl@0: smallFile.Close(); sl@0: } sl@0: sl@0: /** Writes two big files, ensuring the one that started to be written later ends the last one sl@0: sl@0: */ sl@0: void TestTwoBigOnes() sl@0: { sl@0: TInt r = 0; sl@0: TTime time1; sl@0: TTime time2; sl@0: sl@0: // Sync test sl@0: TBuf<20> buf = _L("Big Write IIII"); sl@0: r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: buf = _L("Big Write The Second"); sl@0: r = gSmall.Create(buf, WriteBigFile2, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: gBig.Resume(); sl@0: gSmall.Resume(); sl@0: sl@0: CLIENTWAIT(); sl@0: CLIENTWAIT(); sl@0: sl@0: gBig.Close(); sl@0: gSmall.Close(); sl@0: sl@0: TTimeIntervalMicroSeconds timeTaken = gTime2.MicroSecondsFrom(gTime1); sl@0: test.Printf(_L("\nSync first write ended %d ms before the second write ended (same file size)\n"),I64LOW(timeTaken.Int64() / KuStomS)); sl@0: sl@0: // Async test sl@0: TRequestStatus status[KWaitRequestsTableSize]; sl@0: TRequestStatus status2[KWaitRequestsTableSize]; sl@0: RFile bigFile, bigFile2; sl@0: sl@0: WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize, status); sl@0: WriteFileAsync(TheFs, bigFile2, gSmallFile, gBigFileSize, KBigBlockSize, status2); sl@0: WaitForAll(status, gBigFileSize, KBigBlockSize); sl@0: time1.HomeTime(); sl@0: WaitForAll(status2, gBigFileSize, KBigBlockSize); sl@0: time2.HomeTime(); sl@0: sl@0: timeTaken = time2.MicroSecondsFrom(time1); sl@0: test.Printf(_L("\nAsync first write ended %d ms before the second write ended (same file size)\n"),I64LOW(timeTaken.Int64() / KuStomS)); sl@0: bigFile.Close(); sl@0: bigFile2.Close(); sl@0: } sl@0: sl@0: /** Reads the file that is being written sl@0: sl@0: */ sl@0: void TestReadingWhileWritingSameFile() sl@0: { sl@0: TInt r = 0; sl@0: TTime time1; sl@0: sl@0: time1.HomeTime(); sl@0: sl@0: // Sync test sl@0: TBuf<20> buf = _L("Big Write IV"); sl@0: r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: buf = _L("Read IV"); sl@0: r = gSmall.Create(buf, ReadBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: gBig.Resume(); sl@0: gSmall.Resume(); sl@0: sl@0: CLIENTWAIT(); sl@0: CLIENTWAIT(); sl@0: sl@0: CLOSE_AND_WAIT(gBig); sl@0: CLOSE_AND_WAIT(gSmall); sl@0: sl@0: TTimeIntervalMicroSeconds timeTaken = gTime2.MicroSecondsFrom(gTime1); sl@0: test.Printf(_L("\nSync write finished %d ms before the read ended\n"),I64LOW(timeTaken.Int64() / KuStomS)); sl@0: sl@0: } sl@0: sl@0: /** Client dying uncleanly before the operation is finished sl@0: sl@0: */ sl@0: void TestClientDies() sl@0: { sl@0: TInt r = 0; sl@0: sl@0: sl@0: TBuf<20> drive = _L("?:\\"); sl@0: TVolumeInfo volInfo; sl@0: drive[0]=(TText)(gDrive+'A'); sl@0: sl@0: r = TheFs.CheckDisk(drive); sl@0: TEST(r == KErrNone || r == KErrNotSupported); sl@0: sl@0: // Sync test sl@0: TBuf<20> buf = _L("Big Write V"); sl@0: r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: TRequestStatus status; sl@0: gBig.Logon(status); sl@0: gBig.Resume(); sl@0: gSync.Wait(); sl@0: sl@0: // Kill the writing thread and wait for it to die. sl@0: sl@0: if(status.Int() == KRequestPending) sl@0: {// the people who wrote this test did not consider the case when the file write finishes before they try to kill the thread. sl@0: gBig.Kill(KErrGeneral); sl@0: User::WaitForRequest(status); sl@0: TEST(gBig.ExitReason() == KErrGeneral); sl@0: TEST(gBig.ExitType() == EExitKill); sl@0: } sl@0: sl@0: sl@0: // Make sure the thread is destroyed and the handles it owned and IPCs sl@0: // it executed are closed/cancelled. sl@0: CLOSE_AND_WAIT(gBig); sl@0: sl@0: sl@0: r = TheFs.Volume(volInfo, gDrive); sl@0: TESTERROR(r); sl@0: sl@0: r = TheFs.CheckDisk(drive); sl@0: TEST(r == KErrNone || r == KErrNotSupported); sl@0: sl@0: r = TheFs.ScanDrive(drive); sl@0: TEST(r == KErrNone || r == KErrNotSupported); sl@0: sl@0: test.Printf(_L("Sync operation stopped\n")); sl@0: sl@0: // Async test sl@0: buf = _L("Big Write VI"); sl@0: r = gSmall.Create(buf, WriteBigFileAsync, KDefaultStackSize * 2, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: gSmall.Logon(status); sl@0: gSmall.Resume(); sl@0: gSync.Wait(); sl@0: sl@0: sl@0: if(status.Int() == KRequestPending) sl@0: { sl@0: // Kill the writing thread and wait for it to die. sl@0: gSmall.Kill(KErrGeneral); sl@0: User::WaitForRequest(status); sl@0: TEST(gSmall.ExitReason() == KErrGeneral); sl@0: TEST(gSmall.ExitType() == EExitKill); sl@0: } sl@0: sl@0: sl@0: // Make sure the thread is destroyed and the handles it owned and IPCs sl@0: // it executed are closed/cancelled. sl@0: CLOSE_AND_WAIT(gSmall); sl@0: sl@0: r = TheFs.CheckDisk(drive); sl@0: TEST(r == KErrNone || r == KErrNotSupported); sl@0: sl@0: r=TheFs.ScanDrive(drive); sl@0: TEST(r == KErrNone || r == KErrNotSupported); sl@0: sl@0: test.Printf(_L("Async operation stopped\n")); sl@0: } sl@0: sl@0: /** Reads a small file while writing a big one sl@0: sl@0: */ sl@0: void TestDeletionWhileWriting() sl@0: { sl@0: TInt r = 0; sl@0: sl@0: // Sync test sl@0: TBuf<20> buf = _L("Big Write V"); sl@0: r = gBig.Create(buf, WriteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: buf = _L("Deletion"); sl@0: r = gSmall.Create(buf, DeleteBigFile, KDefaultStackSize, KHeapSize, KMaxHeapSize, NULL); sl@0: TEST(r == KErrNone); sl@0: sl@0: gSmall.Resume(); sl@0: gBig.Resume(); sl@0: sl@0: CLIENTWAIT(); sl@0: CLIENTWAIT(); sl@0: sl@0: gBig.Close(); sl@0: gSmall.Close(); sl@0: sl@0: test.Printf(_L("The file was properly blocked when writing sync, not deleted\n")); sl@0: sl@0: // Async test sl@0: TRequestStatus status[KWaitRequestsTableSize]; sl@0: RFile bigFile; sl@0: RFs fs; sl@0: sl@0: r = fs.Connect(); sl@0: TESTERROR(r); sl@0: r = fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: WriteFileAsync(TheFs, bigFile, gBigFile, gBigFileSize, KBigBlockSize, status); sl@0: sl@0: r = fs.Delete(gBigFile); sl@0: TEST(r == KErrInUse); sl@0: sl@0: WaitForAll(status, gBigFileSize, KBigBlockSize); sl@0: sl@0: bigFile.Close(); sl@0: fs.Close(); sl@0: sl@0: test.Printf(_L("The file was properly blocked when writing async, not deleted\n")); sl@0: sl@0: } sl@0: sl@0: sl@0: void TestWriteOrder() sl@0: { sl@0: RFs fs; sl@0: sl@0: TInt r = fs.Connect(); sl@0: TESTERROR(r); sl@0: r = fs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: WriteOrderTest(TheFs, gBigFileSize, KBlockSize); sl@0: sl@0: fs.Close(); sl@0: } sl@0: sl@0: sl@0: /** Main tests function sl@0: */ sl@0: void CallTestsL() sl@0: { sl@0: TBuf16<45> dir; sl@0: TInt r = 0; sl@0: sl@0: sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: test.Printf(_L("Disabling Lock Fail simulation ...\n")); sl@0: // turn OFF lock failure mode (if cache is enabled) sl@0: sl@0: TBool simulatelockFailureMode = EFalse; sl@0: r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); sl@0: test (r == KErrNone || r == KErrNotSupported); sl@0: #endif sl@0: sl@0: // FileNames/File generation sl@0: test.Start(_L("Preparing the environment\n")); sl@0: sl@0: FileNameGen(gSmallFile, 8, gNextFile++); sl@0: FileNameGen(gBigFile, 8, gNextFile++); sl@0: sl@0: dir = gSessionPath; sl@0: dir.Append(gSmallFile); sl@0: sl@0: gSmallFile = dir; sl@0: dir = gSessionPath; sl@0: dir.Append(gBigFile); sl@0: gBigFile = dir; sl@0: sl@0: TRAPD(res,gBuf = HBufC8::NewL(KBigBlockSize)); sl@0: TEST(res == KErrNone && gBuf != NULL); sl@0: sl@0: gBufWritePtr.Set(gBuf->Des()); sl@0: FillBuffer(gBufWritePtr, KBigBlockSize, 'B'); sl@0: sl@0: TRAPD(res2, gBufSec = HBufC8::NewL(KBlockSize)); sl@0: TEST(res2 == KErrNone && gBufSec != NULL); sl@0: gBufReadPtr.Set(gBufSec->Des()); sl@0: sl@0: test.Next(_L("Benchmarking\n")); sl@0: TimeTakenToWriteBigFile(0); sl@0: TimeTakenToWriteBigFileAsync(0); sl@0: sl@0: test.Printf(_L("second try, second timings account for the last comparison\n")); sl@0: TimeTakenToWriteBigFile(0); sl@0: TimeTakenToWriteBigFileAsync(0); sl@0: sl@0: TimeTakenToWriteBigBlock(); sl@0: sl@0: test.Next(_L("Big file sync written, small file read from the media at the same time\n")); sl@0: TestReadingWhileWriting(); sl@0: sl@0: test.Next(_L("Big file written, small file written at the same time\n")); sl@0: TestWritingWhileWriting(); sl@0: sl@0: test.Next(_L("Big file written async, deletion in the meantime\n")); sl@0: TestDeletionWhileWriting(); sl@0: sl@0: test.Next(_L("Two big files written at the same time\n")); sl@0: TestTwoBigOnes(); sl@0: sl@0: test.Next(_L("Big file being written, start reading\n")); sl@0: TestReadingWhileWritingSameFile(); sl@0: sl@0: test.Next(_L("Client dying unexpectedly\n")); sl@0: TestClientDies(); sl@0: sl@0: test.Next(_L("Ensure write order is preserved\n")); sl@0: TestWriteOrder(); sl@0: sl@0: // Format the drive to make sure no blocks are left to be erased in LFFS sl@0: #if !defined(__WINS__) sl@0: Format(gDrive); sl@0: #endif sl@0: r = TheFs.MkDirAll(gSessionPath); sl@0: sl@0: TimeTakenToWriteBigFile(1); sl@0: TimeTakenToWriteBigFileAsync(1); sl@0: sl@0: // Make sure that the difference between the first time and the last time the files are written doesn't sl@0: // differ more than 3% sl@0: test.Printf(_L("Abs(gTotalTimeSync[0]-gTotalTimeSync[1]) :%d\n"), Abs(gTotalTimeSync[0]-gTotalTimeSync[1])); sl@0: test.Printf(_L("Abs(gTotalTimeAsync[0]-gTotalTimeAsync[1]) :%d\n"), Abs(gTotalTimeAsync[0]-gTotalTimeAsync[1])); sl@0: test.Printf(_L("gTotalTimeSync[0] :%d\n"), gTotalTimeSync[0]); sl@0: test.Printf(_L("gTotalTimeAsync[0] :%d\n"), gTotalTimeAsync[0]); sl@0: sl@0: #if !defined(__WINS__) sl@0: test((Abs(gTotalTimeSync[0]-gTotalTimeSync[1])/gTotalTimeSync[0]) < 0.03); sl@0: test((Abs(gTotalTimeAsync[0]-gTotalTimeAsync[1])/gTotalTimeAsync[0]) < 0.03); sl@0: #endif sl@0: sl@0: r = DeleteAll(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: delete gBuf; sl@0: delete gBufSec; sl@0: sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: // turn lock failure mode back ON (if cache is enabled) sl@0: simulatelockFailureMode = ETrue; sl@0: r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); sl@0: test (r == KErrNone || r == KErrNotSupported); sl@0: #endif sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: /** Initialises semaphores and call the tests sl@0: */ sl@0: void DoTests() sl@0: { sl@0: TInt r = 0; sl@0: sl@0: r = client.CreateLocal(0); sl@0: TESTERROR(r); sl@0: sl@0: r = gSync.CreateLocal(0); sl@0: TESTERROR(r); sl@0: sl@0: r = TheFs.SetSessionPath(gSessionPath); sl@0: TESTERROR(r); sl@0: sl@0: r = TheFs.MkDirAll(gSessionPath); sl@0: if (r != KErrNone && r != KErrAlreadyExists) sl@0: { sl@0: TESTERROR(r); sl@0: } sl@0: TheFs.ResourceCountMarkStart(); sl@0: TRAP(r,CallTestsL()); sl@0: if (r == KErrNone) sl@0: TheFs.ResourceCountMarkEnd(); sl@0: else sl@0: { sl@0: TESTERROR(r); sl@0: } sl@0: } sl@0: sl@0: /** Determines the space that can be used for the files sl@0: sl@0: */ sl@0: TBool CheckForDiskSize() sl@0: { sl@0: TVolumeInfo volInfo; sl@0: TInt r = TheFs.Volume(volInfo, gDrive); sl@0: TESTERROR(r); sl@0: sl@0: gMediaSize = volInfo.iSize; sl@0: gSmallFileSize = KBlockSize; sl@0: gBigFileSize = KBlockSize*20; sl@0: sl@0: while(((2*gBigFileSize)+KOneMeg) > gMediaSize ) sl@0: { sl@0: gBigFileSize -= (2*KBlockSize); sl@0: } sl@0: sl@0: TReal32 small = (TReal32)(gSmallFileSize/KOneK); sl@0: TReal32 big = (TReal32)(gBigFileSize/KOneK); sl@0: sl@0: sl@0: test.Printf(_L("Small File Size: %.2f KB\n"), small); sl@0: test.Printf(_L("Big File Size: %.2f KB (%.2f MB)\n"), big, big / KOneK); sl@0: sl@0: if(gBigFileSize< (3*gSmallFileSize)) sl@0: return EFalse; sl@0: else sl@0: return ETrue; sl@0: } sl@0: sl@0: /** Formats the drive sl@0: sl@0: @param aDrive Drive to be formatted sl@0: */ sl@0: void Format(TInt aDrive) sl@0: { sl@0: sl@0: test.Next(_L("Format")); sl@0: TBuf<4> driveBuf = _L("?:\\"); sl@0: driveBuf[0] = (TText)(aDrive+'A'); sl@0: RFormat format; sl@0: TInt count, prevcount = 0; sl@0: TInt r = format.Open(TheFs, driveBuf, EQuickFormat, count); sl@0: TESTERROR(r); sl@0: sl@0: while(count) sl@0: { sl@0: TInt r = format.Next(count); sl@0: if(count != prevcount) sl@0: { sl@0: test.Printf(_L(".")); sl@0: prevcount = count; sl@0: } sl@0: TESTERROR(r); sl@0: } sl@0: sl@0: format.Close(); sl@0: } sl@0: sl@0: /** Main function sl@0: sl@0: @return KErrNone if everything was ok, panics otherwise sl@0: */ sl@0: TInt E32Main() sl@0: { sl@0: RThread t; sl@0: gMainThreadId = t.Id(); sl@0: sl@0: CTrapCleanup* cleanup; sl@0: cleanup = CTrapCleanup::New(); sl@0: sl@0: __UHEAP_MARK; sl@0: test.Start(_L("Starting tests... T_FSCHED")); sl@0: parseCommandLine(); sl@0: sl@0: TInt r = TheFs.Connect(); sl@0: TESTERROR(r); sl@0: sl@0: TDriveInfo info; sl@0: TVolumeInfo volInfo; sl@0: r = TheFs.Drive(info, gDrive); sl@0: TESTERROR(r); sl@0: sl@0: if(info.iMediaAtt&KMediaAttVariableSize) sl@0: { sl@0: test.Printf(_L("Tests skipped in RAM drive\n")); sl@0: goto out; sl@0: } sl@0: sl@0: r = TheFs.Volume(volInfo, gDrive); sl@0: if (r == KErrNotReady) sl@0: { sl@0: if (info.iType == EMediaNotPresent) sl@0: test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)gDrive + 'A'); sl@0: else sl@0: 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'); sl@0: } sl@0: else if (r == KErrCorrupt) sl@0: { sl@0: test.Printf(_L("%c: Media corruption; previous test may have aborted; else, check hardware\n"), (TUint)gDrive + 'A'); sl@0: } sl@0: TESTERROR(r); sl@0: #if !defined(__WINS__) sl@0: if ((volInfo.iDrive.iMediaAtt & KMediaAttFormattable)) sl@0: Format(gDrive); sl@0: #endif sl@0: sl@0: if(CheckForDiskSize()) sl@0: { sl@0: DoTests(); sl@0: } sl@0: else sl@0: { sl@0: test.Printf(_L("Skipping tests due to lack of space to perform them in this drive\n")); sl@0: } sl@0: out: sl@0: test.End(); sl@0: sl@0: TheFs.Close(); sl@0: test.Close(); sl@0: sl@0: __UHEAP_MARKEND; sl@0: delete cleanup; sl@0: return(KErrNone); sl@0: }