sl@0: // Copyright (c) 2007-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_wcache.cpp sl@0: // This file contains a test for the Write Caching functionality of the File Server 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: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "t_server.h" sl@0: #include sl@0: sl@0: const TInt KTotalCacheSize = 32 * 1024 * 1024; sl@0: const TInt KDefaultCacheSize = (128 + 12) * 1024; // This size is the default configuration size sl@0: const TInt KFilesNeededToFillCache = (KTotalCacheSize / KDefaultCacheSize) + 2; sl@0: const TInt KMinSize = 254; // Boundary minim limit sl@0: const TInt KMaxSize = 257; // Boundary max limit sl@0: sl@0: sl@0: sl@0: //---------------------------------------------------------------------------------------------- sl@0: //! @SYMTestCaseID PBASE-T_WCACHE-0271 sl@0: //! @SYMTestType CIT sl@0: //! @SYMPREQ PREQ914 sl@0: //! @SYMTestCaseDesc This test case is exercising the Write Caching 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 sl@0: //! 1 TestBoundaries writes/reads around the write cache boundaries to sl@0: //! the behaviour of the cache in some common cases. sl@0: //! 2 TestNegative ensures the integrity of data in the cache gets sl@0: //! preserved under error conditions sl@0: //! 3 TestIntegrity is trying to make sure integrity of the data is preserved sl@0: //! 4 TestFillCache fills the cache and then executes TestBoundaries. sl@0: //! 5 TestFillCacheNegative fills the cache with uncommitted data sl@0: //! sl@0: //! @SYMTestExpectedResults finishes if the read cache behaves as expected, panics otherwise sl@0: //! @SYMTestPriority High sl@0: //! @SYMTestStatus Implemented sl@0: //---------------------------------------------------------------------------------------------- sl@0: sl@0: sl@0: //////////////////////////////////////////////////////////// sl@0: // Template functions encapsulating ControlIo magic sl@0: // sl@0: template sl@0: 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: RTest test(_L("T_WCACHE")); sl@0: sl@0: RFs gTheFs; sl@0: TInt gDrive; sl@0: TFileName gSessionPath; sl@0: TChar gDriveToTest; sl@0: TThreadId gMainThreadId; sl@0: TInt gManual = 0; 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 KOneK = 1024; sl@0: const TInt KOneMeg = KOneK * 1024; sl@0: const TInt KBlockSize = KOneK; sl@0: const TInt KWaitRequestsTableSize = 256; sl@0: const TInt KMs = 1000; sl@0: sl@0: TInt gSecondFileSize = 0; sl@0: TInt gFirstFileSize = 0; sl@0: sl@0: TInt64 gMediaSize = 0; sl@0: sl@0: TTimeIntervalMicroSeconds gTimeTakenBigFile(0); sl@0: TBuf16<25> gFirstFile; sl@0: TBuf16<25> gSecondFile; sl@0: TBuf16<25> gCurrentFile; sl@0: sl@0: TInt gNextFile = 0; sl@0: TTime gTime1; sl@0: TTime gTime2; sl@0: sl@0: sl@0: // Concurrent Threads sl@0: RThread gThread1; sl@0: RSemaphore gClient; sl@0: const TInt KHeapSize = 0x4000; sl@0: const TInt KMaxHeapSize = 0x100000; sl@0: sl@0: sl@0: /** Formats the drive sl@0: sl@0: @param aDrive Drive to be formatted sl@0: @param aFormatMode Mode for the format operation sl@0: */ sl@0: void Formatting(TInt aDrive, TUint aFormatMode ) 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; sl@0: TInt r = format.Open(gTheFs,driveBuf,aFormatMode,count); sl@0: test_KErrNone(r); sl@0: while(count) sl@0: { sl@0: TInt r = format.Next(count); sl@0: test_KErrNone(r); sl@0: } sl@0: format.Close(); sl@0: sl@0: } sl@0: sl@0: /** Verifies the content of a buffer sl@0: This function returns KErrNone when all the letters are consecutive in the aBuffer, KErrCorrupt otherwise 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) sl@0: { sl@0: TChar c = aBuffer[0]; sl@0: sl@0: for(TInt i = 1; i < aBuffer.Length(); i++) sl@0: { sl@0: if(i%32 != 0) sl@0: { sl@0: if(c != (TChar)(aBuffer[i] - 1)) sl@0: return KErrCorrupt; sl@0: } sl@0: else sl@0: { sl@0: if(aBuffer[i] != aBuffer[0]) sl@0: return KErrCorrupt; sl@0: } sl@0: c = aBuffer[i]; sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** Fills a buffer with character aC, aC+1, aC+2, ..., aC+0x20, aC, etc sl@0: sl@0: @param aBuffer Buffer to be filled, output sl@0: @param aLength Length to be filled sl@0: @param aC Character to be used to fill the buffer sl@0: */ sl@0: void FillBuffer(TDes8& aBuffer, TInt aLength, TChar aC) sl@0: { sl@0: test (aBuffer.MaxLength() >= aLength); sl@0: for(TInt i = 0; i < aLength; i++) sl@0: { sl@0: aBuffer.Append((i%32) + aC); sl@0: } sl@0: } sl@0: sl@0: /** Returns true if fat filesystem present on aDrive sl@0: sl@0: @param aFsSession Session on the File Server sl@0: @param aDrive Drive to be looked at sl@0: sl@0: @return ETrue if FAT, EFalse otherwise sl@0: */ sl@0: TBool IsFSFAT(RFs &aFsSession,TInt aDrive) sl@0: { sl@0: TFileName f; sl@0: TInt r = aFsSession.FileSystemName(f,aDrive); sl@0: sl@0: if (r != KErrNone) sl@0: { sl@0: test.Printf(_L("Unable to get file system name\n")); sl@0: return EFalse; sl@0: } sl@0: sl@0: return (f.CompareF(_L("Fat")) == 0); 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 < padding) sl@0: { sl@0: aBuffer.Append('F'); sl@0: i++; sl@0: } sl@0: aBuffer.Append(tempbuf); sl@0: sl@0: _LIT(KExtension1, ".TXT"); sl@0: aBuffer.Append(KExtension1); 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 DeleteAllL(TDes16& aDir) sl@0: { sl@0: TBuf16<100> dir; sl@0: CFileMan* fMan = CFileMan::NewL(gTheFs); 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: /** Waits for all the TRequestStatus in status[] to complete sl@0: sl@0: @param status Array of TRequestStatus sl@0: @param aSize Length to be filled sl@0: */ sl@0: void WaitForAll(TRequestStatus* status, TInt aSize) sl@0: { sl@0: TInt i = 0; sl@0: sl@0: RTest test(_L("T_WCACHE")); sl@0: sl@0: while(i < aSize) sl@0: { sl@0: User::WaitForRequest(status[i]); sl@0: if (status[i] != KErrNone) sl@0: { sl@0: test.Printf(_L("status[%d] == %d\n"), i, status[i].Int()); sl@0: test(EFalse); sl@0: } sl@0: i++; sl@0: } sl@0: sl@0: test.Close(); sl@0: } sl@0: sl@0: /** Reads the parameters from the comand line sl@0: and updates the appropriate variables sl@0: */ sl@0: void parseCommandLine() sl@0: { sl@0: TBuf<0x100> 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 = gTheFs.CharToDrive(gDriveToTest,gDrive); sl@0: test_KErrNone(r); sl@0: sl@0: if(!lex.Eos()) sl@0: { sl@0: token.Set(lex.NextToken()); sl@0: if(token.Length() != 0) sl@0: { sl@0: TChar c = token[0]; sl@0: c.UpperCase(); sl@0: sl@0: gManual = (c == 'M'); sl@0: } sl@0: } sl@0: sl@0: gSessionPath = _L("?:\\F32-TST\\"); sl@0: gSessionPath[0] = (TUint16) gDriveToTest; sl@0: test.Printf(_L("\nCLP=%C\n"),(TInt)gDriveToTest); sl@0: } sl@0: sl@0: sl@0: sl@0: /** Writes a file synchronously in blocks of aBlockSize size sl@0: sl@0: @param aFs RFs object sl@0: @param aFile File sl@0: @param aFileName 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 aBuf Buffer to be used to write sl@0: @param aMode Mode in which the file is meant to be opened sl@0: sl@0: @return Returns KErrNone if everything ok, otherwise it panics sl@0: */ sl@0: TInt WriteFile(RFs& aFs, RFile& aFile, TDes16& aFileName, TInt aSize, TInt aBlockSize, TDes8& aBuf, TInt aMode) sl@0: { sl@0: RTest test(_L("T_WCACHE")); sl@0: sl@0: TInt r = 0; sl@0: sl@0: test(aBlockSize > 0); sl@0: sl@0: sl@0: r = aFile.Replace(aFs,aFileName,aMode); sl@0: test_KErrNone(r); sl@0: sl@0: TInt j = 0; sl@0: while(j < aSize) sl@0: { sl@0: r = aFile.Write(aBuf, aBlockSize); sl@0: test_KErrNone(r); sl@0: j += aBlockSize; sl@0: } sl@0: sl@0: test.Close(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** Write a file that fits in the cache, and dies without proper cleaning sl@0: sl@0: */ sl@0: LOCAL_C TInt WriteFileT(TAny* ) sl@0: { sl@0: RTest test(_L("T_WCACHE")); sl@0: RFs fs; sl@0: RFile file; sl@0: TInt r = fs.Connect(); sl@0: test_KErrNone(r); sl@0: sl@0: r = fs.SetSessionPath(gSessionPath); sl@0: test_KErrNone(r); sl@0: sl@0: r = WriteFile(fs, file, gFirstFile, KMinSize * KOneK, KBlockSize, gBufWritePtr, EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: test_KErrNone(r); sl@0: sl@0: gClient.Signal(); sl@0: sl@0: sl@0: FOREVER sl@0: { sl@0: // waiting for the kill sl@0: } sl@0: } sl@0: sl@0: /** Read File in blocks of size aBlockSize sl@0: sl@0: @param aFs RFs object sl@0: @param aFile File sl@0: @param aFileName File name sl@0: @param aSize Expected file size sl@0: @param aBlockSize Size of the blocks to be used in bytes sl@0: @param aMode Mode in which the file is meant to be opened sl@0: sl@0: @return Returns KErrNone if everything ok, otherwise it panics sl@0: */ sl@0: TInt ReadFile(RFs& aFs, RFile& aFile, TDes16& aFileName, TInt aSize, TInt aBlockSize, TInt aMode) sl@0: { sl@0: RTest test(_L("T_WCACHE")); 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: r = aFile.Open(aFs,aFileName,aMode); sl@0: test_KErrNone(r); sl@0: sl@0: // Make sure the size of the file is the right one at this stage sl@0: r = aFile.Size(size); sl@0: test.Printf(_L("size of the file: %d \n"), size/KOneK); sl@0: test(size == aSize); sl@0: sl@0: TInt j = 0; sl@0: while(j < size) sl@0: { sl@0: r = aFile.Read(gBufReadPtr, aBlockSize); sl@0: test_KErrNone(r); sl@0: j += aBlockSize; sl@0: } sl@0: sl@0: test.Close(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** Write a file asynchronously in blocks of aBlockSize size sl@0: sl@0: @param aFs 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 aMode Specifies the mode in which the file should be openned sl@0: @param aStatus TRequestStatus array for all the requests sl@0: */ sl@0: void WriteFileAsync(RFs& aFs, RFile& aFileWrite, TDes16& aFile, TInt aSize, TInt aMode, TRequestStatus aStatus[]) sl@0: { sl@0: RTest test(_L("T_WCACHE")); sl@0: sl@0: TInt r = 0; sl@0: sl@0: r = aFileWrite.Replace(aFs,aFile,aMode); sl@0: test_KErrNone(r); sl@0: sl@0: TInt j = 0, i = 0; sl@0: while(j < aSize) sl@0: { sl@0: aFileWrite.Write(gBufWritePtr, KBlockSize, aStatus[i]); sl@0: r = aStatus[i].Int(); sl@0: if (r != KErrNone && r != KRequestPending) sl@0: { sl@0: test.Printf(_L("Write %d returned %d\n"), i, r); sl@0: test(0); sl@0: } sl@0: i++; sl@0: sl@0: j += KBlockSize; sl@0: } sl@0: test.Close(); sl@0: } sl@0: sl@0: /** Read a file asynchronously in blocks of aBlockSize size sl@0: sl@0: @param aFs 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 aFileSize 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: @param aMode Specifies the mode in which the file should be openned sl@0: sl@0: @return KErrNone sl@0: */ sl@0: TInt ReadFileAsync(RFs& aFs,RFile& aFileRead, TDes16& aFile, TInt aFileSize, TInt aBlockSize,TRequestStatus aStatus[], TInt aMode) sl@0: { sl@0: RTest test(_L("T_WCACHE")); sl@0: sl@0: TInt r = 0; sl@0: TInt size = 0; sl@0: sl@0: test(aBlockSize > 0); sl@0: sl@0: sl@0: r = aFileRead.Open(aFs,aFile, aMode); sl@0: test_KErrNone(r); sl@0: sl@0: r = aFileRead.Size(size); sl@0: test_KErrNone(r); sl@0: sl@0: test.Printf(_L("size of the file %d\n"), size/KOneK); sl@0: test(size == aFileSize); 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: r = aStatus[i].Int(); sl@0: if (r != KErrNone && r != KRequestPending) sl@0: { sl@0: test.Printf(_L("Read %d returned %d\n"), i, r); sl@0: test(0); sl@0: } sl@0: i++; sl@0: sl@0: j += aBlockSize; sl@0: } sl@0: sl@0: test.Close(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** Measure the time taken for this file to be written synchronously sl@0: sl@0: @param aFile File object sl@0: @param aFileName File Name sl@0: @param aSize Size in kilobytes sl@0: @param aBlockSize Size of the block sl@0: @param aMode Mode in which the file is going to be opened sl@0: sl@0: @return time taken to perform the operation in uS sl@0: */ sl@0: TInt WriteTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aBlockSize, TInt aMode) sl@0: { sl@0: RTest test(_L("T_WCACHE")); sl@0: sl@0: TTime startTime; sl@0: TTime endTime; sl@0: TInt r = 0; sl@0: sl@0: startTime.HomeTime(); sl@0: sl@0: r = WriteFile(gTheFs,aFile, aFileName , aSize * KOneK, aBlockSize, gBufWritePtr, aMode); sl@0: test_KErrNone(r); sl@0: sl@0: endTime.HomeTime(); sl@0: sl@0: gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()); sl@0: sl@0: test.Close(); sl@0: return I64LOW(gTimeTakenBigFile.Int64()); sl@0: } sl@0: sl@0: /** Measure the time taken for this file to be read synchronously sl@0: sl@0: @param aFile File object sl@0: @param aFileName File Name sl@0: @param aSize Size in kilobytes sl@0: @param aBlockSize Size of the block sl@0: @param aMode Mode in which the file is going to be opened sl@0: sl@0: @return time taken to perform the operation in uS sl@0: sl@0: */ sl@0: TInt ReadTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aBlockSize, TInt aMode) sl@0: { sl@0: TTime startTime; sl@0: TTime endTime; sl@0: sl@0: startTime.HomeTime(); sl@0: ReadFile(gTheFs,aFile, aFileName, aSize * KOneK, aBlockSize, aMode); sl@0: endTime.HomeTime(); sl@0: sl@0: gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()); sl@0: sl@0: return I64LOW(gTimeTakenBigFile.Int64()) ; sl@0: } sl@0: sl@0: /** Read asynchronously the test file from the disc sl@0: sl@0: @param aFile File object sl@0: @param aFileName File Name sl@0: @param aSize Size in kilobytes sl@0: @param aBlockSize Size of the block sl@0: @param aMode Mode in which the file is going to be opened sl@0: sl@0: @return time taken to perform the operation in uS sl@0: */ sl@0: TInt ReadAsyncTestFile(RFile& file, TDes16& aFile, TInt aSize, TInt aBlockSize, TInt aMode) sl@0: { sl@0: TTime startTime; sl@0: TTime endTime; sl@0: TRequestStatus status[KWaitRequestsTableSize]; sl@0: sl@0: startTime.HomeTime(); sl@0: sl@0: ReadFileAsync(gTheFs, file, aFile, aSize * KOneK, aBlockSize, status, aMode); sl@0: WaitForAll(status, (aSize * KOneK)/KBlockSize); sl@0: sl@0: endTime.HomeTime(); sl@0: sl@0: gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()); sl@0: sl@0: return I64LOW(gTimeTakenBigFile.Int64()); sl@0: } sl@0: sl@0: /** Read asynchronously the test file from the disc sl@0: sl@0: @param aFile File object sl@0: @param aFileName File Name sl@0: @param aSize Size in kilobytes sl@0: @param aMode Mode in which the file is going to be opened sl@0: sl@0: @return time taken to perform the operation in uS sl@0: */ sl@0: TInt WriteAsyncTestFile(RFile& aFile, TDes16& aFileName, TInt aSize, TInt aMode) sl@0: { sl@0: TTime startTime; sl@0: TTime endTime; sl@0: TRequestStatus status[KWaitRequestsTableSize]; sl@0: sl@0: startTime.HomeTime(); sl@0: sl@0: WriteFileAsync(gTheFs, aFile, aFileName, aSize * KOneK, aMode, status ); sl@0: WaitForAll(status, (aSize * KOneK)/KBlockSize); sl@0: sl@0: endTime.HomeTime(); sl@0: sl@0: gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()); sl@0: sl@0: return I64LOW(gTimeTakenBigFile.Int64()); sl@0: } sl@0: sl@0: /** Test Boundaries sl@0: sl@0: This function is testing the behaviour on the boundaries of the write cache size sl@0: */ sl@0: void TestBoundaries() sl@0: { sl@0: TInt r = 0; sl@0: TInt time = 0; sl@0: TInt rtime = 0; sl@0: TInt tcreate = 0; sl@0: RFile fileWriter; sl@0: RFile fileWriter2; sl@0: RFile fileReader; sl@0: sl@0: test.Start(_L("Test Boundaries")); sl@0: sl@0: // Test boundaries from 254K to 256K, synchronous operations sl@0: TInt i = KMinSize; sl@0: sl@0: sl@0: test.Printf(_L("\n\n\n")); sl@0: sl@0: while(i < KMaxSize) sl@0: { sl@0: test.Printf(_L("\nSync: Write from 1 K to %d K \n"), i); sl@0: sl@0: tcreate = WriteTestFile(fileWriter, gSecondFile, i, KBlockSize, EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: test.Printf(_L("Time to write %d K without caching: %d mS\n"), i, tcreate/KMs); sl@0: fileWriter.Close(); sl@0: sl@0: time = WriteTestFile(fileWriter2, gFirstFile, i, KBlockSize, EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), i, time/KMs); sl@0: sl@0: rtime = ReadTestFile(fileReader, gFirstFile, i, KBlockSize, EFileShareAny|EFileRead|EFileReadBuffered); sl@0: test.Printf(_L("Time to read %d K from the cache: %d mS\n"), i, rtime/KMs); sl@0: sl@0: sl@0: fileReader.Close(); sl@0: fileWriter2.Close(); sl@0: sl@0: #if !defined(__WINS__) sl@0: test((tcreate > time) || (tcreate > rtime)); sl@0: #endif sl@0: sl@0: r = gTheFs.Delete(gFirstFile); sl@0: test_KErrNone(r); sl@0: r = gTheFs.Delete(gSecondFile); sl@0: test_KErrNone(r); sl@0: sl@0: i++; sl@0: } sl@0: sl@0: test.Printf(_L("\n\n\n")); sl@0: sl@0: // Test boundaries from 254K to 256K, asynchronous operations sl@0: i = KMinSize; sl@0: sl@0: while(i < KMaxSize) sl@0: { sl@0: test.Printf(_L("\nAsync: Write from 1 K to %d K \n"), i); sl@0: sl@0: tcreate = WriteAsyncTestFile(fileWriter, gSecondFile, i, EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: test.Printf(_L("Time to write %d K without caching: %d mS\n"), i, tcreate/KMs); sl@0: fileWriter.Close(); sl@0: sl@0: time = WriteAsyncTestFile(fileWriter2, gFirstFile, i,EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), i, time/KMs); sl@0: sl@0: sl@0: rtime = ReadAsyncTestFile(fileReader, gFirstFile, i, KBlockSize, EFileShareAny|EFileRead|EFileReadBuffered); sl@0: test.Printf(_L("Time to read %d K from the cache: %d mS\n"), i, rtime/KMs); sl@0: sl@0: fileReader.Close(); sl@0: fileWriter2.Close(); sl@0: sl@0: #if !defined(__WINS__) sl@0: test((tcreate > time) || (tcreate > rtime)); sl@0: #endif sl@0: sl@0: r = gTheFs.Delete(gFirstFile); sl@0: test_KErrNone(r); sl@0: r = gTheFs.Delete(gSecondFile); sl@0: test_KErrNone(r); sl@0: sl@0: i++; sl@0: } sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: /** Test negative cases sl@0: sl@0: */ sl@0: void TestNegative() sl@0: { sl@0: TInt r = 0; sl@0: RFile file; sl@0: TInt size =0; sl@0: sl@0: TBuf<20> buf = _L("Write File"); sl@0: sl@0: sl@0: test.Start(_L("Test Negative")); sl@0: sl@0: test.Next(_L("Kill a simple operation")); sl@0: sl@0: r = gThread1.Create(buf,WriteFileT,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL); sl@0: test_KErrNone(r); sl@0: sl@0: gThread1.Resume(); sl@0: gClient.Wait(); sl@0: sl@0: gThread1.Kill(KErrGeneral); sl@0: sl@0: r = file.Open(gTheFs,gFirstFile,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff); sl@0: test_KErrNone(r); sl@0: sl@0: r = file.Size(size); sl@0: test_KErrNone(r); sl@0: sl@0: test.Printf(_L("The size of the file is %d KB\n\n"), size/KOneK); sl@0: test(size == (KMinSize * KOneK)); sl@0: sl@0: file.Close(); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: sl@0: /** Read the file verifying content sl@0: sl@0: @param aFile file name to verify sl@0: sl@0: @return returns the time that took to do the verification in mS, fails if the file is not corrupted/modified sl@0: */ sl@0: TInt ReadTestFileVerif(TDes16& aFile) sl@0: { sl@0: TTime startTime; sl@0: TTime endTime; sl@0: TInt r = 0; sl@0: TInt size = 0; sl@0: RFile fileRead; sl@0: TInt corrupt = 0; sl@0: TBool isFat=IsFSFAT(gTheFs,gDrive); sl@0: sl@0: startTime.HomeTime(); sl@0: sl@0: r = fileRead.Open(gTheFs,aFile,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff); sl@0: test_KErrNone(r); sl@0: sl@0: r = fileRead.Size(size); sl@0: test_KErrNone(r); sl@0: sl@0: TInt j = 0; sl@0: sl@0: while(j < size) sl@0: { sl@0: r = fileRead.Read(gBufReadPtr, KBlockSize); sl@0: if(isFat) sl@0: { sl@0: test_KErrNone(r); sl@0: } sl@0: else sl@0: { sl@0: if(r == KErrCorrupt) sl@0: corrupt++; sl@0: } sl@0: sl@0: j += KBlockSize; sl@0: r = VerifyBuffer(gBufReadPtr); sl@0: if(r == KErrCorrupt) sl@0: corrupt++; sl@0: } sl@0: sl@0: fileRead.Close(); sl@0: sl@0: test(corrupt>0); // Ensure the cache returns the changed content sl@0: sl@0: endTime.HomeTime(); sl@0: sl@0: gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64()); sl@0: sl@0: return I64LOW(gTimeTakenBigFile.Int64()) / KMs; sl@0: } sl@0: sl@0: /** Modifies the second file sl@0: sl@0: */ sl@0: LOCAL_C TInt CorruptSecondFile() sl@0: { sl@0: TInt r = 0; sl@0: RFile fileWrite; sl@0: HBufC8* dummy = NULL; sl@0: TPtr8 dummyPtr(NULL, 0); sl@0: sl@0: TRAPD(res,dummy = HBufC8::NewL(4)); sl@0: test(res == KErrNone && dummy != NULL); sl@0: sl@0: dummyPtr.Set(dummy->Des()); sl@0: FillBuffer(dummyPtr, 4, '1'); sl@0: sl@0: r = fileWrite.Open(gTheFs,gSecondFile,EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: if(r != KErrNone) sl@0: return r; sl@0: TInt pos = 30; sl@0: r = fileWrite.Seek(ESeekStart,pos); sl@0: test_KErrNone(r); sl@0: sl@0: r = fileWrite.Write(dummyPtr); sl@0: if(r != KErrNone) sl@0: return r; sl@0: sl@0: fileWrite.Close(); sl@0: sl@0: delete dummy; sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: /** Integrity testing sl@0: sl@0: */ sl@0: LOCAL_C void TestIntegrity() sl@0: { sl@0: TInt r = 0; sl@0: TInt time; sl@0: TInt tcreate = 0; sl@0: RFile file; sl@0: sl@0: // Modify file in some position sl@0: test.Printf(_L("Overwrite partially a file\n")); sl@0: sl@0: test.Printf(_L("\nSync: Write from 1 K to %d K \n"), 255); sl@0: sl@0: tcreate = WriteTestFile(file, gSecondFile, 255, KBlockSize, EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: test.Printf(_L("Time to write %d K with caching: %d mS\n"), 255, tcreate/KMs); sl@0: file.Close(); sl@0: sl@0: test.Printf(_L("Mess the content that is still in the cache\n")); sl@0: CorruptSecondFile(); sl@0: sl@0: time = ReadTestFileVerif(gSecondFile); sl@0: test.Printf(_L("Time taken to verify: %d\n"),time); sl@0: sl@0: test.Printf(_L("Integrity verified\n")); sl@0: sl@0: r = DeleteAllL(gSessionPath); sl@0: test_KErrNone(r); sl@0: } sl@0: sl@0: /** Creates the files to fill the cache with dirty data sl@0: sl@0: @return KErrNone sl@0: */ sl@0: TInt CreateFilesThread(TAny *) sl@0: { sl@0: TInt i = 0; sl@0: TInt r = 0; sl@0: TBuf16<50> directory; sl@0: sl@0: TBuf16<50> path; sl@0: TBuf16<50> buffer(50); sl@0: RFile file[KFilesNeededToFillCache]; sl@0: sl@0: RTest test(_L("T_WCACHE2")); sl@0: RFs fs; sl@0: sl@0: fs.Connect(); sl@0: sl@0: directory = gSessionPath; sl@0: sl@0: test.Printf(_L("Creating %d files for filling the cache (size %d)\n"), KFilesNeededToFillCache, KDefaultCacheSize); sl@0: sl@0: // create a big buffer to speed things up sl@0: HBufC8* bigBuf = NULL; sl@0: TInt KBigBifferSize = 32 * KOneK; sl@0: sl@0: TRAPD(res,bigBuf = HBufC8::NewL(KBigBifferSize)); sl@0: test(res == KErrNone && bigBuf != NULL); sl@0: sl@0: TPtr8 bigBufWritePtr(NULL, 0); sl@0: bigBufWritePtr.Set(bigBuf->Des()); sl@0: FillBuffer(bigBufWritePtr, KBigBifferSize, 'A'); sl@0: sl@0: i = 0; sl@0: while(i < KFilesNeededToFillCache) sl@0: { sl@0: if (i % 10 == 0) sl@0: test.Printf(_L("Creating file %d of %d...\r"), i, KFilesNeededToFillCache); sl@0: FileNameGen(buffer, 8, i+3) ; sl@0: path = directory; sl@0: path.Append(buffer); sl@0: sl@0: r = file[i].Create(fs,path,EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: if(r == KErrAlreadyExists) sl@0: r = file[i].Open(fs,path,EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: test_KErrNone(r); sl@0: TInt j = 0; sl@0: sl@0: while(j < KDefaultCacheSize) sl@0: { sl@0: bigBufWritePtr.SetLength(Min(KBigBifferSize, KDefaultCacheSize - j)); sl@0: sl@0: r = file[i].Write(bigBufWritePtr); sl@0: test_KErrNone(r); sl@0: j += bigBufWritePtr.Length(); sl@0: } sl@0: sl@0: // Not closing the files is done on purpose, as part of the test sl@0: sl@0: i++; sl@0: } sl@0: test.Printf(_L("\nFiles created\n")); sl@0: delete bigBuf; sl@0: sl@0: gClient.Signal(); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: /** Creates the files to fill the read cache sl@0: sl@0: @param aFiles Number of files needed to fill the cache sl@0: @param aFileSize The file size sl@0: */ sl@0: void CreateFiles(TInt aFiles, TInt aFileSize) sl@0: { sl@0: TInt i = 0; sl@0: TInt r = 0; sl@0: RFile file; sl@0: TBuf16<50> directory; sl@0: sl@0: TBuf16<50> path; sl@0: TBuf16<50> buffer(50); sl@0: sl@0: directory = gSessionPath; sl@0: sl@0: test.Printf(_L("Creating %d files for filling the cache (size %d)\n"), aFiles, aFileSize); sl@0: sl@0: // create a big buffer to speed things up sl@0: HBufC8* bigBuf = NULL; sl@0: const TInt KBigBifferSize = 32 * 1024; sl@0: TRAPD(res,bigBuf = HBufC8::NewL(KBigBifferSize)); sl@0: test(res == KErrNone && bigBuf != NULL); sl@0: sl@0: TPtr8 bigBufWritePtr(NULL, 0); sl@0: bigBufWritePtr.Set(bigBuf->Des()); sl@0: FillBuffer(bigBufWritePtr, KBigBifferSize, 'A'); sl@0: sl@0: i = 0; sl@0: while(i < aFiles) sl@0: { sl@0: if (i % 10 == 0) sl@0: test.Printf(_L("Creating file %d of %d...\r"), i, aFiles); sl@0: FileNameGen(buffer, 8, i+3) ; sl@0: path = directory; sl@0: path.Append(buffer); sl@0: sl@0: // delete file first to ensure it's contents are not in the cache (file may be be on the closed file queue) sl@0: r = gTheFs.Delete(path); sl@0: test_Value(r, r == KErrNone || r == KErrNotFound); sl@0: sl@0: r = file.Create(gTheFs,path,EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: if(r == KErrAlreadyExists) sl@0: r = file.Open(gTheFs,path,EFileShareAny|EFileWrite|EFileWriteDirectIO); sl@0: test_KErrNone(r); sl@0: TInt j = 0; sl@0: while(j < aFileSize) sl@0: { sl@0: bigBufWritePtr.SetLength(Min(KBigBifferSize, aFileSize - j)); sl@0: r = file.Write(bigBufWritePtr); sl@0: test_KErrNone(r); sl@0: j += bigBufWritePtr.Length(); sl@0: } sl@0: sl@0: file.Close(); sl@0: i++; sl@0: } sl@0: test.Printf(_L("\nFiles created\n")); sl@0: delete bigBuf; sl@0: } sl@0: sl@0: /** Fills the read cache sl@0: sl@0: @param aFile Array of files needed to fill the cache sl@0: @param aFiles Number of files needed to fill the cache sl@0: @param aFileSize The file size sl@0: */ sl@0: void FillCache(RFile aFile[KFilesNeededToFillCache], TInt aFiles, TInt aFileSize) sl@0: { sl@0: TInt i = 0; sl@0: TInt r = 0; sl@0: TBuf16<50> directory; sl@0: sl@0: TBuf16<50> path; sl@0: TBuf16<50> buffer(50); sl@0: HBufC8* buf = NULL; sl@0: TPtr8 bufPtr(NULL, 0); sl@0: sl@0: TRAPD(res,buf = HBufC8::NewL(2)); sl@0: test(res == KErrNone && buf != NULL); sl@0: bufPtr.Set(buf->Des()); sl@0: sl@0: directory = gSessionPath; sl@0: sl@0: i = 0; sl@0: while(i < aFiles) sl@0: { sl@0: FileNameGen(buffer, 8, i+3) ; sl@0: path = directory; sl@0: path.Append(buffer); sl@0: r = aFile[i].Open(gTheFs,path,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff); sl@0: test_KErrNone(r); sl@0: sl@0: TInt j = 0; sl@0: while(j < aFileSize) sl@0: { sl@0: r = aFile[i].Read(j,bufPtr); sl@0: test_KErrNone(r); sl@0: j += 4*KOneK; sl@0: } sl@0: sl@0: i++; sl@0: } sl@0: sl@0: delete buf; sl@0: test.Printf(_L("Cache filled\n")); sl@0: } sl@0: sl@0: /** Fills the default cache sl@0: sl@0: */ sl@0: void TestFillCache() sl@0: { sl@0: TInt nFiles = KFilesNeededToFillCache; sl@0: TInt fSize = KDefaultCacheSize; sl@0: RFile file[KFilesNeededToFillCache]; sl@0: TInt r = 0; sl@0: sl@0: if(gMediaSize> ((fSize * nFiles)+gSecondFileSize+gFirstFileSize)) sl@0: { sl@0: test.Start(_L("Creating files for filling the cache\n")); sl@0: CreateFiles(nFiles,fSize); sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: // get number of items on Page Cache sl@0: TFileCacheStats startPageCacheStats; sl@0: r = controlIo(gTheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats); sl@0: test_Value(r, r == KErrNone || r == KErrNotSupported); sl@0: test.Printf(_L("Number of page cache lines on free list at beginning=%d\n"),startPageCacheStats.iFreeCount); sl@0: test.Printf(_L("Number of page cache lines on used list at beginning=%d\n"),startPageCacheStats.iUsedCount); sl@0: test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue); sl@0: #endif sl@0: FillCache(file,nFiles,fSize); sl@0: sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: // get number of items on Page Cache sl@0: r = controlIo(gTheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats); sl@0: test_Value(r, r == KErrNone || r == KErrNotSupported); sl@0: test.Printf(_L("Number of page cache lines on free list at end=%d\n"),startPageCacheStats.iFreeCount); sl@0: test.Printf(_L("Number of page cache lines on used list at end=%d\n"),startPageCacheStats.iUsedCount); sl@0: test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue); sl@0: #endif sl@0: sl@0: TestBoundaries(); sl@0: sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: // get number of items on Page Cache sl@0: r = controlIo(gTheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats); sl@0: test_Value(r, r == KErrNone || r == KErrNotSupported); sl@0: test.Printf(_L("Number of page cache lines on free list after the boundary testing=%d\n"),startPageCacheStats.iFreeCount); sl@0: test.Printf(_L("Number of page cache lines on used list after the boundary testing=%d\n"),startPageCacheStats.iUsedCount); sl@0: test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue); sl@0: #endif sl@0: sl@0: TInt i = 0; sl@0: while( i < KFilesNeededToFillCache ) sl@0: { sl@0: file[i++].Close(); sl@0: } sl@0: sl@0: r = DeleteAllL(gSessionPath); sl@0: test_KErrNone(r); sl@0: sl@0: test.End(); sl@0: } sl@0: else sl@0: test.Printf(_L("Skipping the fill of the cache due to lack of space in the current drive\n")); sl@0: } sl@0: sl@0: /** Fills the cache and generate error situations sl@0: sl@0: */ sl@0: void TestFillCacheNegative() sl@0: { sl@0: TInt nFiles = KFilesNeededToFillCache; sl@0: TInt r = 0; sl@0: sl@0: if(gMediaSize> ((KDefaultCacheSize * nFiles)+gSecondFileSize+gFirstFileSize)) sl@0: { sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: // get number of items on Page Cache sl@0: TFileCacheStats startPageCacheStats; sl@0: r = controlIo(gTheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats); sl@0: test_Value(r, r == KErrNone || r == KErrNotSupported); sl@0: test.Printf(_L("Number of page cache lines on free list at beginning=%d\n"),startPageCacheStats.iFreeCount); sl@0: test.Printf(_L("Number of page cache lines on used list at beginning=%d\n"),startPageCacheStats.iUsedCount); sl@0: test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue); sl@0: #endif sl@0: test.Start(_L("Creating files for filling the cache, with uncommitted data\n")); sl@0: sl@0: TBuf<20> buf = _L("FillCache"); sl@0: sl@0: r = gThread1.Create(buf,CreateFilesThread,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL); sl@0: test_KErrNone(r); sl@0: sl@0: gThread1.Resume(); sl@0: gClient.Wait(); sl@0: sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: // get number of items on Page Cache sl@0: r = controlIo(gTheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats); sl@0: test_Value(r, r == KErrNone || r == KErrNotSupported); sl@0: test.Printf(_L("Number of page cache lines on free list at end=%d\n"),startPageCacheStats.iFreeCount); sl@0: test.Printf(_L("Number of page cache lines on used list at end=%d\n"),startPageCacheStats.iUsedCount); sl@0: test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue); sl@0: #endif sl@0: sl@0: TestBoundaries(); sl@0: sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: // get number of items on Page Cache sl@0: r = controlIo(gTheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats); sl@0: test_Value(r, r == KErrNone || r == KErrNotSupported); sl@0: test.Printf(_L("Number of page cache lines on free list after the boundary testing=%d\n"),startPageCacheStats.iFreeCount); sl@0: test.Printf(_L("Number of page cache lines on used list after the boundary testing=%d\n"),startPageCacheStats.iUsedCount); sl@0: test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue); sl@0: sl@0: User::After(180000); sl@0: sl@0: r = controlIo(gTheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats); sl@0: test_Value(r, r == KErrNone || r == KErrNotSupported); sl@0: test.Printf(_L("Number of page cache lines on free list after the boundary testing=%d\n"),startPageCacheStats.iFreeCount); sl@0: test.Printf(_L("Number of page cache lines on used list after the boundary testing=%d\n"),startPageCacheStats.iUsedCount); sl@0: test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue); sl@0: sl@0: #endif sl@0: test.End(); sl@0: sl@0: r = DeleteAllL(gSessionPath); sl@0: test_KErrNone(r); sl@0: sl@0: } sl@0: else sl@0: test.Printf(_L("Skipping the fill of the cache due to lack of space in the current drive\n")); sl@0: } sl@0: sl@0: sl@0: /** Manual test for card removal sl@0: sl@0: */ sl@0: void TestRemoval() sl@0: { sl@0: TInt time = 0, rtime = 0; sl@0: RFile file1, file2; sl@0: sl@0: sl@0: TInt r = gClient.CreateLocal(0); sl@0: test_KErrNone(r); sl@0: sl@0: r = gTheFs.SetSessionPath(gSessionPath); sl@0: test_KErrNone(r); sl@0: sl@0: r = gTheFs.MkDirAll(gSessionPath); sl@0: test_Value(r, r == KErrNone || r == KErrAlreadyExists); 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 sl@0: TBool simulatelockFailureMode = EFalse; sl@0: r = controlIo(gTheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); sl@0: test_KErrNone(r); sl@0: #endif sl@0: sl@0: TBuf16<45> dir; sl@0: sl@0: // FileNames/File generation sl@0: test.Start(_L("Preparing the environmnet\n")); sl@0: FileNameGen(gFirstFile, 8, gNextFile++); sl@0: FileNameGen(gSecondFile, 8, gNextFile++); sl@0: dir = gSessionPath; sl@0: dir.Append(gFirstFile); sl@0: gFirstFile = dir; sl@0: dir = gSessionPath; sl@0: dir.Append(gSecondFile); sl@0: gSecondFile = dir; sl@0: sl@0: sl@0: TRAPD(res,gBuf = HBufC8::NewL(KBlockSize+1)); sl@0: test(res == KErrNone && gBuf != NULL); sl@0: sl@0: gBufWritePtr.Set(gBuf->Des()); sl@0: FillBuffer(gBufWritePtr, KBlockSize, 'A'); sl@0: sl@0: TRAPD(res2,gBufSec = HBufC8::NewL(KBlockSize+1)); sl@0: test(res2 == KErrNone && gBufSec != NULL); sl@0: gBufReadPtr.Set(gBufSec->Des()); sl@0: sl@0: sl@0: test.Printf(_L("\nSync: Write from 1 K to 254 K \n")); sl@0: sl@0: time = WriteTestFile(file1, gSecondFile, KMinSize, KBlockSize, EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), KMinSize, time/KMs); sl@0: test.Printf(_L("Remove MMC card,! and then press a key\n")); sl@0: test.Getch(); sl@0: sl@0: test.Printf(_L("Wait 3 seconds and insert MMC card! and then press a key\n")); sl@0: test.Getch(); sl@0: sl@0: rtime = ReadTestFile(file2, gSecondFile, KMinSize, KBlockSize, EFileShareAny|EFileRead|EFileReadBuffered); sl@0: test.Printf(_L("Time to read %d K from the cache: %d mS\n"), KMinSize, rtime/KMs); sl@0: sl@0: test.Printf(_L("Remove MMC card! and then press a key\n")); sl@0: test.Getch(); sl@0: sl@0: test.Printf(_L("Wait 3 seconds and insert MMC card! and then press a key\n")); sl@0: test.Getch(); sl@0: sl@0: sl@0: test.Printf(_L("\nSync: Write from 1 K to 255 K \n")); sl@0: sl@0: time = WriteTestFile(file1, gFirstFile, KMinSize + 1 , KBlockSize, EFileShareAny|EFileWrite|EFileWriteBuffered); sl@0: test.Printf(_L("Time to write %d K WITH caching: %d mS\n"), KMinSize + 1, time/KMs); sl@0: test.Printf(_L("Remove MMC card and delete the file //F32-TST//FFFFFFF0.TXT and then press a key\n")); sl@0: test.Getch(); sl@0: sl@0: test.Printf(_L("Wait 3 seconds and insert MMC card! and then press a key\n")); sl@0: test.Getch(); sl@0: sl@0: rtime = ReadTestFile(file2, gFirstFile, KMinSize + 1, KBlockSize, EFileShareAny|EFileRead|EFileReadBuffered); sl@0: test.Printf(_L("Time to read %d K from the cache: %d mS\n"), KMinSize + 1, rtime/KMs); sl@0: sl@0: test.Printf(_L("Remove MMC card! and then press a key\n")); sl@0: test.Getch(); sl@0: sl@0: test.Printf(_L("Wait 3 seconds and insert MMC card! and then press a key\n")); sl@0: test.Getch(); sl@0: sl@0: sl@0: file1.Close(); sl@0: file2.Close(); sl@0: delete gBuf; sl@0: delete gBufSec; sl@0: } sl@0: sl@0: sl@0: /** Main tests function sl@0: */ sl@0: void CallTestsL() 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 sl@0: TBool simulatelockFailureMode = EFalse; sl@0: TInt r = controlIo(gTheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); sl@0: test_KErrNone(r); sl@0: #endif sl@0: sl@0: TBuf16<45> dir; sl@0: sl@0: // FileNames/File generation sl@0: test.Start(_L("Preparing the environmnet\n")); sl@0: FileNameGen(gFirstFile, 8, gNextFile++); sl@0: FileNameGen(gSecondFile, 8, gNextFile++); sl@0: dir = gSessionPath; sl@0: dir.Append(gFirstFile); sl@0: gFirstFile = dir; sl@0: dir = gSessionPath; sl@0: dir.Append(gSecondFile); sl@0: gSecondFile = dir; sl@0: sl@0: sl@0: TRAPD(res,gBuf = HBufC8::NewL(KBlockSize+1)); sl@0: test(res == KErrNone && gBuf != NULL); sl@0: sl@0: gBufWritePtr.Set(gBuf->Des()); sl@0: FillBuffer(gBufWritePtr, KBlockSize, 'A'); sl@0: sl@0: TRAPD(res2,gBufSec = HBufC8::NewL(KBlockSize+1)); sl@0: test(res2 == KErrNone && gBufSec != NULL); sl@0: gBufReadPtr.Set(gBufSec->Des()); sl@0: sl@0: test.Next(_L("Boundary test")); sl@0: TestBoundaries(); sl@0: sl@0: test.Next(_L("Negative test\n")); sl@0: TestNegative(); sl@0: sl@0: test.Next(_L("Integrity test\n")); sl@0: TestIntegrity(); sl@0: sl@0: sl@0: test.Next(_L("Fill the cache, boundary testing\n")); sl@0: TestFillCache(); sl@0: sl@0: test.Next(_L("Fill the cache negative, boundary testing\n")); sl@0: TestFillCacheNegative(); sl@0: sl@0: test.End(); 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 enabled) sl@0: simulatelockFailureMode = ETrue; sl@0: r = controlIo(gTheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); sl@0: test_KErrNone(r); sl@0: #endif sl@0: 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 = gClient.CreateLocal(0); sl@0: test_KErrNone(r); sl@0: sl@0: r = gTheFs.SetSessionPath(gSessionPath); sl@0: test_KErrNone(r); sl@0: sl@0: r = gTheFs.MkDirAll(gSessionPath); sl@0: test_Value(r, r == KErrNone || r == KErrAlreadyExists); sl@0: gTheFs.ResourceCountMarkStart(); sl@0: sl@0: TRAP(r,CallTestsL()); sl@0: sl@0: test_KErrNone(r); sl@0: gTheFs.ResourceCountMarkEnd(); 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 = gTheFs.Volume(volInfo, gDrive); sl@0: test_KErrNone(r); sl@0: gMediaSize = volInfo.iSize; sl@0: sl@0: test.Printf(_L("\nMedia size: %d MB\n"), gMediaSize/KOneMeg ); sl@0: sl@0: return ETrue; 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_WCACHE")); sl@0: parseCommandLine(); sl@0: sl@0: TInt r = gTheFs.Connect(); sl@0: test_KErrNone(r); sl@0: sl@0: TDriveInfo info; sl@0: TVolumeInfo volInfo; sl@0: r = gTheFs.Drive(info,gDrive); sl@0: test_KErrNone(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 = gTheFs.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)gDriveToTest); sl@0: else sl@0: 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); 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)gDriveToTest); sl@0: } sl@0: test_KErrNone(r); sl@0: sl@0: if(!(volInfo.iFileCacheFlags & (EFileCacheReadEnabled | EFileCacheReadAheadEnabled))) sl@0: { sl@0: test.Printf(_L("Skipping tests, Read caching not enabled in this drive\n")); sl@0: goto out; sl@0: } sl@0: sl@0: if (((volInfo.iDrive.iMediaAtt & KMediaAttFormattable))) sl@0: Formatting(gDrive,ESpecialFormat); sl@0: sl@0: if(!CheckForDiskSize()) 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: else if(!gManual) sl@0: { sl@0: DoTests(); sl@0: } sl@0: else sl@0: { sl@0: TestRemoval(); sl@0: } sl@0: sl@0: out: sl@0: test.End(); sl@0: sl@0: gTheFs.Close(); sl@0: test.Close(); sl@0: sl@0: __UHEAP_MARKEND; sl@0: delete cleanup; sl@0: return(KErrNone); sl@0: } sl@0: