1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/f32test/server/t_filecache.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1813 @@
1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// f32test\server\t_filecache.cpp
1.18 +//
1.19 +//
1.20 +#define __E32TEST_EXTENSION__
1.21 +#include <f32file.h>
1.22 +#include <e32test.h>
1.23 +#include <e32svr.h>
1.24 +#include <f32dbg.h>
1.25 +#include "t_server.h"
1.26 +#include <e32twin.h>
1.27 +#include <e32rom.h>
1.28 +
1.29 +
1.30 +//----------------------------------------------------------------------------------------------
1.31 +//! @SYMTestCaseID PBASE-T_FILECACHE-0189
1.32 +//! @SYMTestType UT
1.33 +//! @SYMPREQ PREQ914
1.34 +//! @SYMTestCaseDesc Unit tests for fair scheduling, read caching and lazy writing
1.35 +//! @SYMTestActions 0 setup the environment to execute the tests
1.36 +//! 1 Reads a file with different blocksizes
1.37 +//! 2 Write a file with different blocksizes
1.38 +//! 3 Small reads while controlling the cache
1.39 +//! 4 Read operations with and without read ahead
1.40 +//! 5 Write operations with write buffer
1.41 +//! @SYMTestExpectedResults finishes if the implementation of PREQ914 behaves as expected, panics otherwise
1.42 +//! @SYMTestPriority High
1.43 +//! @SYMTestStatus Critical
1.44 +//----------------------------------------------------------------------------------------------
1.45 +
1.46 +
1.47 +//#define SYMBIAN_TEST_EXTENDED_BUFFER_SIZES
1.48 +
1.49 +
1.50 +GLDEF_D RTest test(_L("T_FILECACHE"));
1.51 +
1.52 +GLDEF_D RFs TheFs;
1.53 +GLDEF_D TChar gDriveToTest;
1.54 +GLDEF_D TInt gDrive;
1.55 +GLDEF_D TFileName gSessionPath;
1.56 +
1.57 +GLDEF_D TVolumeInfo gVolInfo; // volume info for current drive
1.58 +GLDEF_D TFileCacheFlags gDriveCacheFlags = TFileCacheFlags(0);
1.59 +
1.60 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.61 +static TFileCacheConfig gFileCacheConfig;
1.62 +static TBool gDisplayCacheFlags = EFalse;
1.63 +static TBool gWriteCacheFlags = EFalse;
1.64 +static TBool gRomPaged = EFalse;
1.65 +#endif
1.66 +static TBool gRunTests = ETrue;
1.67 +static TBool gRunUnitTests = ETrue;
1.68 +static TBool gRunPerformanceTests = EFalse;
1.69 +static TBool gRunManualTests = EFalse;
1.70 +
1.71 +
1.72 +LOCAL_D TInt KMaxFileSize = 768 * 1024;
1.73 +
1.74 +// Chosing a file size of 128K ensures entire file will be cached
1.75 +//LOCAL_D TInt KMaxFileSize = 128 * 1024;
1.76 +
1.77 +LOCAL_D TBuf8<256*1024> DataBuf;
1.78 +
1.79 +const TInt KBufSize = 513 * 1024 - 16;
1.80 +HBufC8* gBuf = NULL;
1.81 +
1.82 +
1.83 +LOCAL_D TPtr8 gBufPtr(NULL, 0);
1.84 +
1.85 +const TReal KOneK = 1024;
1.86 +const TReal KOneMeg = 1024 * KOneK;
1.87 +
1.88 +const TInt KSegmentSize = 4096;
1.89 +const TInt KSegmentSizeMask = (4096-1);
1.90 +
1.91 +GLDEF_D template <class C>
1.92 +GLDEF_C TInt controlIo(RFs &fs, TInt drv, TInt fkn, C &c)
1.93 +{
1.94 + TPtr8 ptrC((TUint8 *)&c, sizeof(C), sizeof(C));
1.95 +
1.96 + TInt r = fs.ControlIo(drv, fkn, ptrC);
1.97 +
1.98 + return r;
1.99 +}
1.100 +
1.101 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.102 +void PrintFileCacheStats(TFileCacheStats& fileCacheStats, TBool aDisplay = ETrue)
1.103 + {
1.104 + TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheStats, fileCacheStats);
1.105 + test_KErrNone(r);
1.106 + if (!aDisplay)
1.107 + return;
1.108 + test.Printf(_L("File cache: Cachelines (free %d, used %d), Segments(allocated %d locked %d). Closed files(%d) Holes %d Failures (commit %d Lock %d)\n"),
1.109 + fileCacheStats.iFreeCount, fileCacheStats.iUsedCount, fileCacheStats.iAllocatedSegmentCount,fileCacheStats.iLockedSegmentCount,fileCacheStats.iFilesOnClosedQueue, fileCacheStats.iHoleCount, fileCacheStats.iCommitFailureCount, fileCacheStats.iLockFailureCount);
1.110 + test.Printf(_L("File cache: iUncachedPacketsRead %d iUncachedBytesRead %d iUncachedPacketsWritten %d iUncachedBytesWritten %d\n"),
1.111 + fileCacheStats.iUncachedPacketsRead,
1.112 + fileCacheStats.iUncachedBytesRead,
1.113 + fileCacheStats.iUncachedPacketsWritten,
1.114 + fileCacheStats.iUncachedBytesWritten);
1.115 + }
1.116 +
1.117 +void PrintFileCacheConfig(TFileCacheConfig& aFileCacheConfig, TBool aDisplay = ETrue)
1.118 + {
1.119 + TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheConfig, aFileCacheConfig);
1.120 + test (r == KErrNone);
1.121 + if (!aDisplay)
1.122 + return;
1.123 +
1.124 + test.Printf(_L("File cache:\nDrive %c\nFlags %08X\nFileCacheReadAsync %d\nFairSchedulingLen %d\nCacheSize %d\nMaxReadAheadLen %d\nClosedFileKeepAliveTime %d\nDirtyDataFlushTime %d"),
1.125 + aFileCacheConfig.iDrive + 'A',
1.126 + aFileCacheConfig.iFlags,
1.127 + aFileCacheConfig.iFileCacheReadAsync,
1.128 + aFileCacheConfig.iFairSchedulingLen,
1.129 + aFileCacheConfig.iCacheSize,
1.130 + aFileCacheConfig.iMaxReadAheadLen,
1.131 + aFileCacheConfig.iClosedFileKeepAliveTime,
1.132 + aFileCacheConfig.iDirtyDataFlushTime);
1.133 +
1.134 + }
1.135 +
1.136 +void TestDirtyDataWrittenToDisk(TFileCacheStats& fileCacheStats)
1.137 + {
1.138 + test.Next(_L("test dirty data has been written to disk"));
1.139 + // wait a maximum of double KDefaultDirtyDataFlushTime for dirty data to be flushed
1.140 + const TInt KWaitTime = 250; // 250 milisecs
1.141 + for (TInt n=0; n<(gFileCacheConfig.iDirtyDataFlushTime/1000)<<1 ; n+= KWaitTime)
1.142 + {
1.143 + test.Printf(_L("After %d milisecs : "), n );
1.144 + PrintFileCacheStats(fileCacheStats);
1.145 + User::After(KWaitTime * 1000); // wait 100 ms
1.146 + if (fileCacheStats.iLockedSegmentCount == 0)
1.147 + break;
1.148 + }
1.149 + PrintFileCacheStats(fileCacheStats);
1.150 + test(fileCacheStats.iLockedSegmentCount == 0);
1.151 + }
1.152 +#endif
1.153 +
1.154 +void TestsInit()
1.155 + {
1.156 + gBuf = HBufC8::NewL(KBufSize);
1.157 + test(gBuf!=NULL);
1.158 + gBufPtr.Set(gBuf->Des());
1.159 + }
1.160 +void TestsEnd()
1.161 + {
1.162 + delete gBuf;
1.163 + gBuf = NULL;
1.164 + }
1.165 +
1.166 +LOCAL_C void SetSessionPath(TInt aDrive)
1.167 + {
1.168 + gSessionPath=_L("?:\\F32-TST\\");
1.169 + TChar driveLetter;
1.170 + TInt r=TheFs.DriveToChar(aDrive,driveLetter);
1.171 + test_KErrNone(r);
1.172 + gSessionPath[0]=(TText)driveLetter;
1.173 + r=TheFs.SetSessionPath(gSessionPath);
1.174 + test_KErrNone(r);
1.175 + }
1.176 +
1.177 +LOCAL_C void PrintFileMode(TUint aFileMode)
1.178 + {
1.179 + TBuf<80> buf;
1.180 +
1.181 + buf.Format(_L("FileMode = %08X"), aFileMode);
1.182 +
1.183 + if (aFileMode & EFileWriteBuffered)
1.184 + buf.Append(_L(", EFileWriteBuffered"));
1.185 +
1.186 + if (aFileMode & EFileWriteDirectIO)
1.187 + buf.Append(_L(", EFileWriteDirectIO"));
1.188 +
1.189 + if (aFileMode & EFileReadBuffered)
1.190 + buf.Append(_L(", EFileReadBuffered"));
1.191 +
1.192 + if (aFileMode & EFileReadDirectIO)
1.193 + buf.Append(_L(", EFileReadDirectIO"));
1.194 +
1.195 + if (aFileMode & EFileReadAheadOn)
1.196 + buf.Append(_L(", EFileReadAheadOn"));
1.197 +
1.198 + if (aFileMode & EFileReadAheadOff)
1.199 + buf.Append(_L(", EFileReadAheadOff"));
1.200 +
1.201 + buf.Append(_L("\n"));
1.202 + test.Printf(buf);
1.203 + }
1.204 +
1.205 +void FillBuffer(TDes8& aBuffer, TInt aLength)
1.206 + {
1.207 + test (aBuffer.MaxLength() >= aLength);
1.208 + for(TInt i=0; i<aLength; i+=2)
1.209 + {
1.210 + aBuffer[i]=(TUint8) (i >> 8);
1.211 + aBuffer[i+1]=(TUint8) i;
1.212 + }
1.213 + }
1.214 +
1.215 +void TestBufferFail(TDes8& aBuffer, TInt aPos, TInt aLength)
1.216 + {
1.217 + test.Printf(_L("TestBuffer failed at pos %d len %d\n"), aPos, aLength);
1.218 +
1.219 + #define PRINTCH(ch) ((ch >= 0x20 && ch < 0x7F)?ch:' ')
1.220 + TInt startPos = Max(0, aPos - 64);
1.221 + TInt endPos = startPos + 64;
1.222 +
1.223 + for(TInt n=startPos; n<=endPos; n+=16)
1.224 + RDebug::Print(_L("%08X: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]"),
1.225 + //&aBuffer[aPos+n],
1.226 + n,
1.227 + aBuffer[n+0], aBuffer[n+1], aBuffer[n+2], aBuffer[n+3], aBuffer[n+4], aBuffer[n+5], aBuffer[n+6], aBuffer[n+7], aBuffer[n+8], aBuffer[n+9], aBuffer[n+10], aBuffer[n+11], aBuffer[n+12], aBuffer[n+13], aBuffer[n+14], aBuffer[n+15],
1.228 + PRINTCH(aBuffer[n+0]), PRINTCH(aBuffer[n+1]), PRINTCH(aBuffer[n+2]), PRINTCH(aBuffer[n+3]), PRINTCH(aBuffer[n+4]), PRINTCH(aBuffer[n+5]), PRINTCH(aBuffer[n+6]), PRINTCH(aBuffer[n+7]), PRINTCH(aBuffer[n+8]), PRINTCH(aBuffer[n+9]), PRINTCH(aBuffer[n+10]), PRINTCH(aBuffer[n+11]), PRINTCH(aBuffer[n+12]), PRINTCH(aBuffer[n+13]), PRINTCH(aBuffer[n+14]), PRINTCH(aBuffer[n+15]));
1.229 +
1.230 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.231 + TInt x;
1.232 + TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheDump, x);
1.233 + test_KErrNone(r);
1.234 +#endif
1.235 + test (0);
1.236 + }
1.237 +
1.238 +void TestBuffer(TDes8& aBuffer, TInt aPos, TInt aLength)
1.239 + {
1.240 + TInt pos = aPos;
1.241 + for(TInt i=0; i<aLength; i++, pos++)
1.242 + {
1.243 + if (pos & 1)
1.244 + {
1.245 + if (aBuffer[pos] != (TUint8) pos-1)
1.246 + TestBufferFail(aBuffer, pos, aLength);
1.247 + }
1.248 + else
1.249 + {
1.250 + if (aBuffer[pos] != (TUint8) (pos >> 8))
1.251 + TestBufferFail(aBuffer, pos, aLength);
1.252 + }
1.253 + }
1.254 + }
1.255 +
1.256 +
1.257 +LOCAL_C void UnitTests()
1.258 +//
1.259 +// Test read file handling.
1.260 +//
1.261 + {
1.262 +
1.263 + test.Start(_L("File cache read and write unit tests"));
1.264 +
1.265 +//TheFs.SetDebugRegister(KCACHE);
1.266 +
1.267 + RFile f;
1.268 + TInt r;
1.269 + TInt pos;
1.270 + TInt len;
1.271 + TInt testNum;
1.272 +
1.273 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.274 + TBool simulatelockFailureMode;
1.275 + TFileCacheStats fileCacheStats;
1.276 + r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats);
1.277 + test (r == KErrNone);
1.278 + test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue);
1.279 + test(fileCacheStats.iFilesOnClosedQueue == 0);
1.280 +#endif
1.281 +
1.282 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.283 + // turn OFF lock failure mode
1.284 + simulatelockFailureMode = EFalse;
1.285 + r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode);
1.286 + test (r == KErrNone);
1.287 +#endif
1.288 +
1.289 + TFileName testFile = _L("TEST.BIN");
1.290 +
1.291 + //**********************************
1.292 + // Test Read-Modify-Write
1.293 + //**********************************
1.294 + test.Next(_L("Test read-modify-write"));
1.295 + gBufPtr.SetLength(KBufSize);
1.296 + FillBuffer(gBufPtr, KBufSize);
1.297 + TestBuffer(gBufPtr, 0,KBufSize);
1.298 + TPtrC8 writePtr;
1.299 + TPtr8 readPtr(gBuf->Des());
1.300 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.301 + TInt uncachedBytesRead;
1.302 + TInt uncachedPacketsRead;
1.303 +#endif
1.304 +
1.305 + // create an empty file, so that any writes overlapping segemt boundaries
1.306 + // need a read first
1.307 + // create a test file using directIO and then re-open it in buffered mode,
1.308 + // so that any writes overlapping segemt boundaries need a read first
1.309 + r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteDirectIO);
1.310 + test_KErrNone(r);
1.311 + writePtr.Set(gBuf->Des());
1.312 + r = f.Write(0, writePtr);
1.313 + test_KErrNone(r);
1.314 + f.Close();
1.315 + r = f.Open(TheFs, testFile, EFileReadBuffered | EFileWrite | EFileWriteBuffered);
1.316 + test_KErrNone(r);
1.317 +
1.318 + TInt cacheLineLen = 128*1024;
1.319 +
1.320 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.321 + PrintFileCacheStats(fileCacheStats);
1.322 + uncachedBytesRead = fileCacheStats.iUncachedBytesRead;
1.323 + uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead;
1.324 +#endif
1.325 +
1.326 + // write 1 partial segment at offset 0 to 7 in segment
1.327 + test.Next(_L("Test read-modify-write #1"));
1.328 + pos = cacheLineLen*0 + KSegmentSize*2 + 0;
1.329 + len = 7;
1.330 + writePtr.Set(gBuf->Mid(pos, len));
1.331 + r = f.Write(pos, writePtr, len);
1.332 + test_KErrNone(r);
1.333 + // read back & verify whole segment
1.334 + pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask;
1.335 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.336 + readPtr.SetLength(len);
1.337 + readPtr.FillZ();
1.338 + r = f.Read(pos, readPtr, len);
1.339 + test_KErrNone(r);
1.340 + TestBuffer(gBufPtr, pos, len);
1.341 + test_KErrNone(r);
1.342 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.343 + PrintFileCacheStats(fileCacheStats);
1.344 + test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize);
1.345 + test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 1);
1.346 + uncachedBytesRead = fileCacheStats.iUncachedBytesRead;
1.347 + uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead;
1.348 +#endif
1.349 +
1.350 + // write 1 partial segment at offset 7 to 4096 in segment
1.351 + test.Next(_L("Test read-modify-write #2"));
1.352 + pos = cacheLineLen*0 + KSegmentSize*3 + 7;
1.353 + len = KSegmentSize - 7;
1.354 + writePtr.Set(gBuf->Mid(pos, len));
1.355 + r = f.Write(pos, writePtr, len);
1.356 + test_KErrNone(r);
1.357 + // read back & verify whole segment
1.358 + pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask;
1.359 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.360 + readPtr.SetLength(len);
1.361 + readPtr.FillZ();
1.362 + r = f.Read(pos, readPtr, len);
1.363 + test_KErrNone(r);
1.364 + TestBuffer(gBufPtr, pos, len);
1.365 + test_KErrNone(r);
1.366 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.367 + PrintFileCacheStats(fileCacheStats);
1.368 + test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize);
1.369 + test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 1);
1.370 + uncachedBytesRead = fileCacheStats.iUncachedBytesRead;
1.371 + uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead;
1.372 +#endif
1.373 +
1.374 + // write 1 partial segment at offset 7 to 37 in segment
1.375 + test.Next(_L("Test read-modify-write #3"));
1.376 + pos = cacheLineLen*0 + KSegmentSize*4 + 7;
1.377 + len = 30;
1.378 + writePtr.Set(gBuf->Mid(pos, len));
1.379 + r = f.Write(pos, writePtr, len);
1.380 + test_KErrNone(r);
1.381 + // read back & verify whole segment
1.382 + pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask;
1.383 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.384 + readPtr.SetLength(len);
1.385 + readPtr.FillZ();
1.386 + r = f.Read(pos, readPtr, len);
1.387 + test_KErrNone(r);
1.388 + TestBuffer(gBufPtr, pos, len);
1.389 + test_KErrNone(r);
1.390 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.391 + PrintFileCacheStats(fileCacheStats);
1.392 + test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize);
1.393 + test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 1);
1.394 + uncachedBytesRead = fileCacheStats.iUncachedBytesRead;
1.395 + uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead;
1.396 +#endif
1.397 +
1.398 + // write 2 segments, first and last both partial
1.399 + test.Next(_L("Test read-modify-write #4"));
1.400 + pos = cacheLineLen*1 + KSegmentSize*2 + 3;
1.401 + len = KSegmentSize * 1;
1.402 + writePtr.Set(gBuf->Mid(pos, len));
1.403 + r = f.Write(pos, writePtr, len);
1.404 + test_KErrNone(r);
1.405 + // read back & verify whole segment
1.406 + pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask;
1.407 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.408 + readPtr.SetLength(len);
1.409 + readPtr.FillZ();
1.410 + r = f.Read(pos, readPtr, len);
1.411 + test_KErrNone(r);
1.412 + TestBuffer(gBufPtr, pos, len);
1.413 + test_KErrNone(r);
1.414 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.415 + PrintFileCacheStats(fileCacheStats);
1.416 + test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize*2);
1.417 + // should read both segments in one read as they are contiguous
1.418 + test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 1);
1.419 + uncachedBytesRead = fileCacheStats.iUncachedBytesRead;
1.420 + uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead;
1.421 +#endif
1.422 +
1.423 + // write 3 segments, first and last both partial
1.424 + test.Next(_L("Test read-modify-write #5"));
1.425 + pos = cacheLineLen*2 + KSegmentSize*2 + 7;
1.426 + len = KSegmentSize * 2;
1.427 + writePtr.Set(gBuf->Mid(pos, len));
1.428 + r = f.Write(pos, writePtr, len);
1.429 + test_KErrNone(r);
1.430 + // read back & verify whole segment
1.431 + pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask;
1.432 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.433 + readPtr.SetLength(len);
1.434 + readPtr.FillZ();
1.435 + r = f.Read(pos, readPtr, len);
1.436 + test_KErrNone(r);
1.437 + TestBuffer(gBufPtr, pos, len);
1.438 + test_KErrNone(r);
1.439 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.440 + PrintFileCacheStats(fileCacheStats);
1.441 + test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize*2);
1.442 + test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 2);
1.443 + uncachedBytesRead = fileCacheStats.iUncachedBytesRead;
1.444 + uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead;
1.445 +#endif
1.446 +
1.447 + f.Close();
1.448 +
1.449 + //**************************************************************
1.450 + // Test dirty data NOT written to disk if continuously writing to a file which fits in tke cache
1.451 + //**************************************************************
1.452 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.453 + test.Printf(_L("Test dirty data NOT written to disk if continuously writing to a file which fits in tke cache...\n"));
1.454 +
1.455 + // flush closed files queue to empty cache
1.456 + test.Printf(_L("Flushing close queue to empty cache...\n"));
1.457 + r = TheFs.ControlIo(gDrive, KControlIoFlushClosedFiles);
1.458 + test_KErrNone(r);
1.459 +
1.460 + r = f.Replace(TheFs, testFile, EFileReadBuffered | EFileWrite | EFileWriteBuffered);
1.461 + test_KErrNone(r);
1.462 +
1.463 + RTimer timer;
1.464 + timer.CreateLocal();
1.465 + TRequestStatus reqStat;
1.466 + timer.After(reqStat,gFileCacheConfig.iClosedFileKeepAliveTime*3); // write 3 times the flush timer
1.467 +
1.468 + pos = 0;
1.469 + TInt bufLen = 7;
1.470 + TInt maxLockedSegmentCount = 0;
1.471 + while (reqStat == KRequestPending)
1.472 + {
1.473 + bufLen = (bufLen + 1023) & 0x3FFF;
1.474 + len = Min(bufLen, KBufSize - pos);
1.475 + len = Min(len, gFileCacheConfig.iCacheSize-pos);
1.476 + TPtrC8 writePtr = gBuf->Mid(pos, len);
1.477 + r = f.Write(pos, writePtr, len);
1.478 + test_KErrNone(r);
1.479 + pos+= len;
1.480 + TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheStats, fileCacheStats);
1.481 + test_KErrNone(r);
1.482 + // test the locked (i.e. dirty) count always goes up & never down (down would indicate a flush)
1.483 + if (fileCacheStats.iLockedSegmentCount != maxLockedSegmentCount)
1.484 + test.Printf(_L("iLockedSegmentCount %d...\n"), fileCacheStats.iLockedSegmentCount);
1.485 +
1.486 + test(fileCacheStats.iLockedSegmentCount >= maxLockedSegmentCount);
1.487 + maxLockedSegmentCount = Max(maxLockedSegmentCount, fileCacheStats.iLockedSegmentCount);
1.488 + // wrap to start of file
1.489 + if (pos >= gFileCacheConfig.iCacheSize)
1.490 + pos = 0;
1.491 + }
1.492 + timer.Close();
1.493 +
1.494 + test(fileCacheStats.iLockedSegmentCount > 0);
1.495 +
1.496 + if (gDriveCacheFlags & (EFileCacheWriteEnabled | EFileCacheWriteOn))
1.497 + TestDirtyDataWrittenToDisk(fileCacheStats);
1.498 + f.Close();
1.499 +#endif
1.500 +
1.501 +
1.502 + //**************************************************************
1.503 + // Test dirty data written to disk
1.504 + //**************************************************************
1.505 + enum {ETestDataWrittenAfterTimeout, ETestDataWrittenAfterFileClose, ETestDataWrittenAfterSessionClose, ETestEnd};
1.506 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.507 + for (testNum = 0; testNum < ETestEnd; testNum++)
1.508 +#else
1.509 + for (testNum = 0; testNum < 1; testNum++)
1.510 +#endif
1.511 + {
1.512 + switch(testNum)
1.513 + {
1.514 + case ETestDataWrittenAfterTimeout : test.Next(_L("ETestDataWrittenAfterTimeout")); break;
1.515 + case ETestDataWrittenAfterFileClose : test.Next(_L("ETestDataWrittenAfterFileClose")); break;
1.516 + case ETestDataWrittenAfterSessionClose : test.Next(_L("ETestDataWrittenAfterSessionClose")); break;
1.517 + };
1.518 +
1.519 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.520 + // flush closed files queue to empty cache
1.521 + test.Printf(_L("Flushing close queue to empty cache...\n"));
1.522 + r = TheFs.ControlIo(gDrive, KControlIoFlushClosedFiles);
1.523 + test_KErrNone(r);
1.524 +#endif
1.525 +
1.526 + r = f.Replace(TheFs, testFile, EFileReadBuffered | EFileWrite | EFileWriteBuffered);
1.527 + test_KErrNone(r);
1.528 +
1.529 +
1.530 + gBufPtr.SetLength(KBufSize);
1.531 +
1.532 + test.Printf(_L("writing file in small blocks to test write caching...\n"));
1.533 +
1.534 + FillBuffer(gBufPtr, KBufSize);
1.535 + TestBuffer(gBufPtr, 0,KBufSize);
1.536 +
1.537 + pos = 0;
1.538 + TInt bufLen = 7;
1.539 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.540 + TInt maxLockedSegmentCount = 0;
1.541 + TInt maxUsedCount = 0;
1.542 +#endif
1.543 + while (pos < KBufSize)
1.544 + {
1.545 + bufLen = (bufLen + 1023) & 0x3FFF;
1.546 + len = Min(bufLen, KBufSize - pos);
1.547 +//RDebug::Print(_L("write len %d"), len);
1.548 + TPtrC8 writePtr = gBuf->Mid(pos, len);
1.549 + r = f.Write(pos, writePtr, len);
1.550 + test_KErrNone(r);
1.551 + pos+= len;
1.552 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.553 +// PrintFileCacheStats(fileCacheStats);
1.554 + TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheStats, fileCacheStats);
1.555 + test_KErrNone(r);
1.556 + maxLockedSegmentCount = Max(maxLockedSegmentCount, fileCacheStats.iLockedSegmentCount);
1.557 + maxUsedCount = Max(maxUsedCount, fileCacheStats.iUsedCount);
1.558 +#endif
1.559 + }
1.560 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.561 + test.Next(_L("Test maxiimum locked page and cacheline count is reasonable"));
1.562 + test.Printf(_L("maxLockedSegmentCount %d maxUsedCount %d"), maxLockedSegmentCount, maxUsedCount);
1.563 + test (maxLockedSegmentCount > 0 && maxLockedSegmentCount <= (gFileCacheConfig.iCacheSize * 2) / KSegmentSize );
1.564 + test (maxUsedCount > 0 && maxUsedCount <= 5);
1.565 +#endif
1.566 +
1.567 +
1.568 +
1.569 + if (testNum == ETestDataWrittenAfterTimeout)
1.570 + {
1.571 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.572 + if (gDriveCacheFlags & (EFileCacheWriteEnabled | EFileCacheWriteOn))
1.573 + TestDirtyDataWrittenToDisk(fileCacheStats);
1.574 +#endif
1.575 + f.Close();
1.576 + }
1.577 +
1.578 + if (testNum == ETestDataWrittenAfterFileClose)
1.579 + {
1.580 + f.Close();
1.581 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.582 + test.Next(_L("test dirty data has been written to disk after file close"));
1.583 + PrintFileCacheStats(fileCacheStats);
1.584 + test(fileCacheStats.iLockedSegmentCount == 0);
1.585 +#endif
1.586 + }
1.587 +
1.588 + if (testNum == ETestDataWrittenAfterSessionClose)
1.589 + {
1.590 + // verify that closing the file server session (i.e. not the file)
1.591 + // flushes the data to disk...
1.592 + // *** NB This is likely to complete sometime AFTER returning from RFs::Close()
1.593 + // *** as the file server doesn't wait for the disconnect thread to complete !!!
1.594 +
1.595 + TheFs.Close();
1.596 + TheFs.Connect();
1.597 + SetSessionPath(gDrive);
1.598 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.599 + test.Next(_L("Test dirty data is eventually written to disk after session close"));
1.600 + TestDirtyDataWrittenToDisk(fileCacheStats);
1.601 + test(fileCacheStats.iLockedSegmentCount == 0);
1.602 +#endif
1.603 + }
1.604 +
1.605 + } // for (TInt testNum = 0; testNum < ETestEnd; testNum++)
1.606 +
1.607 +
1.608 +//#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.609 +// PrintFileCacheStats(fileCacheStats);
1.610 +//#endif
1.611 +
1.612 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.613 + // flush closed files queue to empty cache
1.614 + test.Printf(_L("Flushing close queue to empty cache...\n"));
1.615 + r = TheFs.ControlIo(gDrive, KControlIoFlushClosedFiles);
1.616 + test_KErrNone(r);
1.617 +#endif
1.618 +
1.619 + r = f.Open(TheFs, testFile, EFileRead | EFileReadBuffered | EFileWrite);
1.620 + test_KErrNone(r);
1.621 +
1.622 + TInt size;
1.623 + r = f.Size(size);
1.624 + test (r == KErrNone);
1.625 + test (size = KBufSize);
1.626 +
1.627 + readPtr.Set(gBuf->Des());
1.628 +
1.629 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.630 + // Allocate full cachelines - so we can enable hole testing
1.631 + TBool allocateAllSegmentsInCacheLine = ETrue;
1.632 + r = controlIo(TheFs, gDrive, KControlIoAllocateMaxSegments, allocateAllSegmentsInCacheLine);
1.633 + test (r == KErrNone);
1.634 + PrintFileCacheStats(fileCacheStats, EFalse);
1.635 + TInt holesDetected = fileCacheStats.iHoleCount;
1.636 + TInt lockFailures = fileCacheStats.iCommitFailureCount + fileCacheStats.iLockFailureCount;
1.637 +#endif
1.638 +
1.639 + test.Next(_L("Test reading a partially filled cacheline"));
1.640 + // create a cacheline with only the first segment filled
1.641 + TInt startPos = KSegmentSize;
1.642 + pos = startPos;
1.643 + len = KSegmentSize;
1.644 + writePtr.Set(gBuf->Mid(pos, len));
1.645 + r = f.Write(pos, writePtr, len);
1.646 + test_KErrNone(r);
1.647 +
1.648 + // read from first & second segments
1.649 + pos = startPos;
1.650 + len = 8192;
1.651 + RDebug::Print(_L("+%x, %x\n"), pos, len);
1.652 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.653 + readPtr.SetLength(len);
1.654 + r = f.Read(pos, readPtr, len);
1.655 + test_KErrNone(r);
1.656 + TestBuffer(gBufPtr, pos, len);
1.657 +
1.658 +
1.659 + test.Next(_L("Test reading an empty segment towards the end of a partially filled cacheline (hole test)"));
1.660 + // read from segment #4 and beyond end of cacheline into next
1.661 + pos = startPos + KSegmentSize * 4;
1.662 + len = KSegmentSize * 33; // 132 K
1.663 + RDebug::Print(_L("+%x, %x\n"), pos, len);
1.664 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.665 + readPtr.SetLength(len);
1.666 + r = f.Read(pos, readPtr, len);
1.667 + test_KErrNone(r);
1.668 + TestBuffer(gBufPtr, pos, len);
1.669 +
1.670 +
1.671 + test.Next(_L("Test writing to an empty segment towards the end of a partially filled cacheline (hole test)"));
1.672 + // create a cacheline with only the first segment filled
1.673 + startPos = 256 * 1024;
1.674 + pos = startPos;
1.675 + len = KSegmentSize;
1.676 + writePtr.Set(gBuf->Mid(pos, len));
1.677 + r = f.Write(pos, writePtr, len);
1.678 + test_KErrNone(r);
1.679 +
1.680 +
1.681 + // write into segment 3, 4 & 5
1.682 + pos = startPos + KSegmentSize * 2;
1.683 + len = KSegmentSize * 3;
1.684 + writePtr.Set(gBuf->Mid(pos, len));
1.685 + r = f.Write(pos, writePtr, len);
1.686 + test_KErrNone(r);
1.687 + // read back whole cacheline & verify
1.688 + pos = startPos;
1.689 + len = KSegmentSize * 32; // 128 K
1.690 + RDebug::Print(_L("+%x, %x\n"), pos, len);
1.691 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.692 + readPtr.SetLength(len);
1.693 + r = f.Read(pos, readPtr, len);
1.694 + test_KErrNone(r);
1.695 + TestBuffer(gBufPtr, pos, len);
1.696 +
1.697 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.698 + PrintFileCacheStats(fileCacheStats);
1.699 + if (fileCacheStats.iCommitFailureCount + fileCacheStats.iLockFailureCount != lockFailures)
1.700 + {
1.701 + if (gRomPaged)
1.702 + {
1.703 + test.Printf(_L("Lock failures detected on paged ROM, abandoning hole test"));
1.704 + }
1.705 + else
1.706 + {
1.707 + test.Printf(_L("Unexpected lock failures detected on unpaged ROM!!!"));
1.708 + test(0);
1.709 + }
1.710 + }
1.711 + else
1.712 + {
1.713 + test(fileCacheStats.iHoleCount > holesDetected);
1.714 + }
1.715 + // Don't allocate full cachelines any more
1.716 + allocateAllSegmentsInCacheLine = EFalse;
1.717 + r = controlIo(TheFs, gDrive, KControlIoAllocateMaxSegments, allocateAllSegmentsInCacheLine);
1.718 + test (r == KErrNone);
1.719 +#endif
1.720 +
1.721 +
1.722 +
1.723 + gBufPtr.FillZ();
1.724 + gBufPtr.SetLength(KBufSize);
1.725 +
1.726 +
1.727 +
1.728 + readPtr.SetLength(0);
1.729 +
1.730 +
1.731 + // read from middle of fifth sector to half way thru seventh
1.732 + test.Next(_L("Test read that spans two pages"));
1.733 + pos = 512*4 + 16;
1.734 + len = 512*2;
1.735 + RDebug::Print(_L("+%x, %x\n"), pos, len);
1.736 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.737 + readPtr.SetLength(len);
1.738 + r = f.Read(pos, readPtr, len);
1.739 + test_KErrNone(r);
1.740 + TestBuffer(gBufPtr, pos, len);
1.741 +
1.742 +
1.743 +
1.744 + // read to end of file
1.745 + test.Next(_L("Test reading past end of file"));
1.746 + pos = KBufSize - 0x100; // 0xfb05;
1.747 + len = KBufSize - pos;
1.748 +// pos = KBufSize - 16;
1.749 +// len = 512;;
1.750 +// len = Min(len, KBufSize-pos);
1.751 + RDebug::Print(_L("+%x, %x\n"), pos, len);
1.752 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.753 + readPtr.SetLength(len);
1.754 + r = f.Read(pos, readPtr, len/* + 0x67*/);
1.755 + test_KErrNone(r);
1.756 +
1.757 + test.Next(_L("Test async reads"));
1.758 + // issue 2 async reads
1.759 + pos = KSegmentSize*7 + 16;
1.760 + len = KSegmentSize;
1.761 + RDebug::Print(_L("+%x, %x\n"), pos, len);
1.762 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.763 + readPtr.SetLength(len);
1.764 +
1.765 + TInt pos2 = pos + len;
1.766 + TInt len2 = KSegmentSize;
1.767 + TPtr8 readPtr2 = gBuf->Des();
1.768 + readPtr2.Set(gBufPtr.MidTPtr(pos2, len2));
1.769 + readPtr2.SetLength(len2);
1.770 +
1.771 + TRequestStatus status1(KRequestPending);
1.772 + TRequestStatus status2(KRequestPending);
1.773 +
1.774 + f.Read(pos, readPtr, len, status1);
1.775 + f.Read(readPtr2, len2, status2);
1.776 +
1.777 +
1.778 + User::WaitForRequest(status1);
1.779 + User::WaitForRequest(status2);
1.780 + test.Printf(_L("status1 %d status2 %d\n"), status1.Int(), status2.Int());
1.781 + TestBuffer(gBufPtr, pos, len);
1.782 + TestBuffer(gBufPtr, pos2, len2);
1.783 +
1.784 +
1.785 + test.Next(_L("Read entire file"));
1.786 +
1.787 + for (pos = 0, len = 1; len <= 1024 && pos < KBufSize; len = (len+1) & 0x3FF)
1.788 + {
1.789 + len = Min(len, KBufSize-pos);
1.790 +// RDebug::Print(_L("+%x, %x\n"), pos, len);
1.791 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.792 + readPtr.SetLength(len);
1.793 +
1.794 + r = f.Read(pos, readPtr, len);
1.795 + test_KErrNone(r);
1.796 + TestBuffer(gBufPtr, pos, len);
1.797 + test_KErrNone(r);
1.798 + pos+= len;
1.799 + }
1.800 +
1.801 + TestBuffer(gBufPtr, 0, KBufSize);
1.802 +
1.803 + // read from position zero to ensure it's cached
1.804 + pos = 0;
1.805 + len = 512;
1.806 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.807 + readPtr.SetLength(len);
1.808 + r = f.Read(pos, readPtr, len);
1.809 + test_KErrNone(r);
1.810 + TestBuffer(gBufPtr, pos, len);
1.811 + test_KErrNone(r);
1.812 +
1.813 + f.Close();
1.814 +
1.815 +
1.816 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.817 + r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats);
1.818 + test (r == KErrNone);
1.819 + test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue);
1.820 + test(fileCacheStats.iFilesOnClosedQueue == 1);
1.821 +#endif
1.822 + //
1.823 +
1.824 +
1.825 + //**************************************************************
1.826 + // Test closed file queue
1.827 + //**************************************************************
1.828 + enum
1.829 + {
1.830 + ETestCloseQueueEmptyAfterTimeout,
1.831 + ETestCloseQueueEmptyAfterOpenWithDirectIo,
1.832 + ETestCloseQueueEmptyAfterDelete,
1.833 + ETestCloseEnd};
1.834 + for (testNum = 0; testNum < ETestCloseEnd; testNum++)
1.835 + {
1.836 +
1.837 + test.Next(_L("Reopen file & verify closed queue is empty"));
1.838 +
1.839 + r = f.Open(TheFs, testFile, EFileRead | EFileReadBuffered);
1.840 + test_KErrNone(r);
1.841 + pos = 0;
1.842 + len = 512;
1.843 + readPtr.Set(gBufPtr.MidTPtr(pos, len));
1.844 + readPtr.SetLength(len);
1.845 + r = f.Read(pos, readPtr, len);
1.846 + test_KErrNone(r);
1.847 + TestBuffer(gBufPtr, pos, len);
1.848 + test_KErrNone(r);
1.849 +
1.850 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.851 + r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats);
1.852 + test (r == KErrNone);
1.853 + test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue);
1.854 + test(fileCacheStats.iFilesOnClosedQueue == 0);
1.855 +#endif
1.856 + f.Close();
1.857 +
1.858 + test.Next(_L("close & verify file is back on close queue"));
1.859 +
1.860 +
1.861 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.862 + r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats);
1.863 + test (r == KErrNone);
1.864 + test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue);
1.865 + test(fileCacheStats.iFilesOnClosedQueue == 1);
1.866 +#endif
1.867 +
1.868 + if (testNum == ETestCloseQueueEmptyAfterDelete)
1.869 + {
1.870 + test.Next(_L("delete file and verify closed queue is empty"));
1.871 + r = TheFs.Delete(testFile);
1.872 + test_KErrNone(r);
1.873 + }
1.874 + if (testNum == ETestCloseQueueEmptyAfterTimeout)
1.875 + {
1.876 + test.Next(_L("wait for a while and verify closed queue is empty"));
1.877 + // wait for closed file queue to empty
1.878 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.879 + User::After(gFileCacheConfig.iClosedFileKeepAliveTime + 1000000);
1.880 +#endif
1.881 + }
1.882 + if (testNum == ETestCloseQueueEmptyAfterOpenWithDirectIo)
1.883 + {
1.884 + test.Next(_L("Re-open file in directIo mode and then close and verify closed queue is empty"));
1.885 + r = f.Open(TheFs, testFile, EFileRead | EFileReadDirectIO);
1.886 + test_KErrNone(r);
1.887 + f.Close();
1.888 + }
1.889 +
1.890 + #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.891 + r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats);
1.892 + test (r == KErrNone);
1.893 + test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue);
1.894 + test(fileCacheStats.iFilesOnClosedQueue == 0);
1.895 + #endif
1.896 + }
1.897 +
1.898 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.899 + // turn lock failure mode back ON (if enabled)
1.900 + simulatelockFailureMode = ETrue;
1.901 + r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode);
1.902 + test (r == KErrNone);
1.903 +#endif
1.904 +
1.905 + //**************************************************************
1.906 + // Test opening a file with a silly open mode flags combinations
1.907 + //**************************************************************
1.908 + test.Next(_L("Open file with illegal cache on/off bits"));
1.909 + r = f.Open(TheFs, testFile, EFileRead | EFileReadBuffered | EFileReadDirectIO);
1.910 + test_Value(r, r==KErrArgument);
1.911 + r = f.Open(TheFs, testFile, EFileRead | EFileWriteBuffered | EFileWriteDirectIO);
1.912 + test_Value(r, r==KErrArgument);
1.913 + //**********************************
1.914 + // Test that continuously appending to a file yields the correct size...
1.915 + // NB: Must have lock failure more ON in debug mode for this test to pass
1.916 + //**********************************
1.917 + test.Next(_L("Test appending to a file & checking the file size..."));
1.918 + gBufPtr.SetLength(KBufSize);
1.919 +
1.920 + r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteBuffered);
1.921 + test_KErrNone(r);
1.922 +
1.923 + const TInt KWriteLen = KSegmentSize+1;
1.924 + writePtr.Set(gBuf->Des().Ptr(), KWriteLen);
1.925 +
1.926 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.927 + r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats);
1.928 + test (r == KErrNone);
1.929 + test.Printf(_L("Number of Write-throughs with dirty data=%d\n"),fileCacheStats.iWriteThroughWithDirtyDataCount);
1.930 + TInt writeThroughWithDirtyDataCountOld = fileCacheStats.iWriteThroughWithDirtyDataCount;
1.931 + TInt writeThroughWithDirtyDataCountNew = writeThroughWithDirtyDataCountOld;
1.932 +#endif
1.933 +
1.934 + TInt fileSize = 0;
1.935 + for (TInt i=0; i<4; i++)
1.936 + {
1.937 + fileSize = 0;
1.938 + r = f.SetSize(fileSize);
1.939 + test (r == KErrNone);
1.940 + for (pos = 0; pos < KMaxFileSize; )
1.941 + {
1.942 + r = f.Write(pos, writePtr);
1.943 + if (r != KErrNone)
1.944 + {
1.945 + test.Printf(_L("Iter #%d, write pos %d size %d, Write() returned %d"), i, pos, fileSize, r);
1.946 + r = f.Flush();
1.947 + test.Printf(_L("Flush returned %d"), r);
1.948 + test(0);
1.949 + }
1.950 + test(r == KErrNone);
1.951 + pos+= writePtr.Length();
1.952 +
1.953 + r = f.Size(fileSize);
1.954 + test (r == KErrNone);
1.955 + if (fileSize != pos)
1.956 + {
1.957 + test.Printf(_L("Iter #%d, write pos %d != size %d"), i, pos, fileSize);
1.958 + r = f.Flush();
1.959 + test.Printf(_L("Flush returned %d"), r);
1.960 + test(0);
1.961 + }
1.962 + test (fileSize == pos);
1.963 +
1.964 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.965 + r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats);
1.966 + test (r == KErrNone);
1.967 + writeThroughWithDirtyDataCountNew = fileCacheStats.iWriteThroughWithDirtyDataCount;
1.968 + if (writeThroughWithDirtyDataCountNew > writeThroughWithDirtyDataCountOld)
1.969 + {
1.970 + test.Printf(_L("Iter #%d, write pos %d size %d"), i, pos, fileSize);
1.971 + test.Printf(_L("Number of Write-throughs with dirty data=%d\n"),fileCacheStats.iWriteThroughWithDirtyDataCount);
1.972 + i = 4;
1.973 + break;
1.974 + }
1.975 +#endif
1.976 +
1.977 + }
1.978 + }
1.979 +
1.980 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.981 + test(writeThroughWithDirtyDataCountNew > writeThroughWithDirtyDataCountOld);
1.982 +#endif
1.983 +
1.984 +
1.985 + f.Close();
1.986 +
1.987 +
1.988 +//TheFs.SetDebugRegister(0);
1.989 + test.End();
1.990 + }
1.991 +
1.992 +
1.993 +// This thread is used to test what happens if requests are sent to the file server
1.994 +// while the drive thread is hung in the critical notifier server. The requests should
1.995 +// complete immediately with KErrNotReady
1.996 +TInt ReaderThread(TAny* aFileName)
1.997 + {
1.998 + RTest test(_L("T_FILECACHE, ReaderThread"));
1.999 +
1.1000 + TDesC& fileName = *(TDesC*) aFileName;
1.1001 +
1.1002 + RFs fs;
1.1003 + TInt r = fs.Connect();
1.1004 + test (r==KErrNone);
1.1005 + r = fs.SetSessionPath(gSessionPath);
1.1006 + test (r==KErrNone);
1.1007 +
1.1008 +
1.1009 + RFile file;
1.1010 + r = file.Open(fs, fileName, EFileRead | EFileReadBuffered | EFileShareReadersOrWriters);
1.1011 + test_KErrNone(r);
1.1012 +
1.1013 + RTimer timer;
1.1014 + timer.CreateLocal();
1.1015 + TRequestStatus reqStat;
1.1016 + timer.After(reqStat,10000000); // Read for 10 secs
1.1017 +
1.1018 + TInt pos=0;
1.1019 + TInt KReadLen = 32768;
1.1020 + TInt retCode = KErrNone;
1.1021 +
1.1022 + for (TInt i=0; reqStat == KRequestPending; i++)
1.1023 + {
1.1024 + r = file.Read(pos, DataBuf, KReadLen);
1.1025 + test_Value(r, r == KErrNone || r == KErrNotReady);
1.1026 +
1.1027 + //test.Printf(_L("ReaderThread: iter %d, read at %d ret %d\n"), i, pos, r);
1.1028 + if (r == KErrNotReady)
1.1029 + retCode = r;
1.1030 + else if (r == KErrNone)
1.1031 + pos = DataBuf.Length() == 0 ? 0: pos + DataBuf.Length();
1.1032 + if (retCode == KErrNotReady)
1.1033 + test.Printf(_L("ReaderThread: iter %d, read at %d ret %d \n"), i, pos, r);
1.1034 + }
1.1035 +
1.1036 + timer.Close();
1.1037 + file.Close();
1.1038 + fs.Close();
1.1039 +
1.1040 + return retCode;
1.1041 + }
1.1042 +
1.1043 +
1.1044 +void ManualTests()
1.1045 + {
1.1046 + RFile f;
1.1047 + TInt r;
1.1048 + gBufPtr.SetLength(KBufSize);
1.1049 + FillBuffer(gBufPtr, KBufSize);
1.1050 + TestBuffer(gBufPtr, 0,KBufSize);
1.1051 +
1.1052 + TPtrC8 writePtr;
1.1053 + writePtr.Set(gBuf->Des());
1.1054 +
1.1055 + TFileName testFile = _L("TEST.BIN");
1.1056 +
1.1057 +#if defined(_DEBUG)
1.1058 + test.Next(_L("Testing writing and then closing with an immediate simulated card eject"));
1.1059 + test.Printf(_L("**********************************************************\n"));
1.1060 + test.Printf(_L("When critical notifier message appears, PRESS RETRY\n"));
1.1061 + test.Printf(_L("**********************************************************\n"));
1.1062 +
1.1063 + r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteBuffered | EFileShareReadersOrWriters);
1.1064 + test_KErrNone(r);
1.1065 +
1.1066 + test.Printf(_L("Writing...."));
1.1067 + r = f.Write(0, writePtr);
1.1068 + test.Printf(_L("Write returned %d\n"), r);
1.1069 + test_KErrNone(r);
1.1070 +
1.1071 + r=TheFs.ControlIo(gDrive, KControlIoSimulateFileCacheWriteFailure);
1.1072 + test_KErrNone(r);
1.1073 +
1.1074 + f.Close();
1.1075 +
1.1076 + TEntry entry;
1.1077 +
1.1078 + // wait for re-insertion....
1.1079 + do
1.1080 + {
1.1081 + r = TheFs.Entry(testFile, entry);
1.1082 + User::After(500000);
1.1083 + }
1.1084 + while (r == KErrNotReady);
1.1085 + test_KErrNone(r);
1.1086 +
1.1087 + test.Printf(_L("FileSize %d expected %d\n"), entry.iSize, writePtr.Length());
1.1088 +
1.1089 + // test all data is written to disk
1.1090 + test (entry.iSize == writePtr.Length());
1.1091 +#endif
1.1092 +
1.1093 +
1.1094 + test.Next(_L("Testing writing and then ejecting card"));
1.1095 +
1.1096 +// r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteDirectIO);
1.1097 + r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteBuffered | EFileShareReadersOrWriters);
1.1098 + test_KErrNone(r);
1.1099 + writePtr.Set(gBuf->Des());
1.1100 +
1.1101 +
1.1102 + // set the file size first so that the cluster chain already exists
1.1103 + r = f.SetSize(writePtr.Length());
1.1104 + test.Printf(_L("SetSize returned %d"));
1.1105 +
1.1106 + // Create another thread which will attempt to issue reads while this thread is suspended
1.1107 + // These reads should complete with KErrNotReady
1.1108 + const TInt KHeapSize = 32768;
1.1109 + test.Printf(_L("Creating file-reading thread\n"));
1.1110 + RThread readerThread;
1.1111 + readerThread.Create(_L("FileReaderThread"), ReaderThread, KDefaultStackSize, KHeapSize, KHeapSize, &testFile);
1.1112 +
1.1113 + test.Printf(_L("Writing...."));
1.1114 + r = f.Write(0, writePtr);
1.1115 + test.Printf(_L("Write returned %d\n"), r);
1.1116 +
1.1117 +
1.1118 + test.Printf(_L("Waiting 5 seconds.\n"));
1.1119 + test.Printf(_L("**********************************************************\n"));
1.1120 + test.Printf(_L("Please press a key, EJECT MEDIA BEFORE WRITE TIMER EXPIRES,\n"));
1.1121 + test.Printf(_L("wait for critical notifier, replace media and retry\n"));
1.1122 + test.Printf(_L("**********************************************************\n"));
1.1123 +// test.Printf(_L("press any key..."));
1.1124 + test.Getch();
1.1125 + test.Printf(_L("\n"));
1.1126 +
1.1127 + test.Printf(_L("Writing...."));
1.1128 + r = f.Write(0, writePtr);
1.1129 + test.Printf(_L("Write returned %d\n"), r);
1.1130 + readerThread.Resume();
1.1131 +
1.1132 + User::After(5000000);
1.1133 +
1.1134 + do
1.1135 + {
1.1136 + test.Printf(_L("Flushing....\n"));
1.1137 + r = f.Flush();
1.1138 + test.Printf(_L("Flush returned %d\n"), r);
1.1139 + if (r != KErrNone)
1.1140 + User::After(5000000);
1.1141 + }
1.1142 + while (r != KErrNone);
1.1143 +
1.1144 +
1.1145 +// r = f.Write(0, writePtr);
1.1146 +// test.Printf(_L("Write returned %d"));
1.1147 +
1.1148 +// test_KErrNone(r);
1.1149 +
1.1150 + test.Next(_L("Testing reader thread completed with KErrNotReady"));
1.1151 + TRequestStatus status;
1.1152 + readerThread.Logon(status);
1.1153 + readerThread.Resume();
1.1154 + User::WaitForRequest(status);
1.1155 + test.Printf(_L("ReaderThread status %d\n"), status.Int());
1.1156 + test (status.Int() == KErrNotReady);
1.1157 + readerThread.Close();
1.1158 +
1.1159 + test.Printf(_L("press any key..."));
1.1160 + test.Getch();
1.1161 + test.Printf(_L("\n"));
1.1162 +
1.1163 + f.Close();
1.1164 + }
1.1165 +
1.1166 +
1.1167 +LOCAL_C void DoTestFileRead(TUint aFileMode, TInt aReadBlockSize)
1.1168 +//
1.1169 +// Do Read Test
1.1170 +//
1.1171 + {
1.1172 +
1.1173 + RFile file;
1.1174 + TInt r=file.Open(TheFs,_L("READTEST.XXX"),EFileStream | aFileMode);
1.1175 + test_KErrNone(r);
1.1176 +
1.1177 + TInt maxReadCount=KMaxFileSize/aReadBlockSize;
1.1178 + TInt loopCount=0;
1.1179 +
1.1180 + TTime startTime;
1.1181 + TTime endTime;
1.1182 +
1.1183 + RTimer timer;
1.1184 + timer.CreateLocal();
1.1185 + TRequestStatus reqStat;
1.1186 + timer.After(reqStat,10000000); // After 10 secs
1.1187 + startTime.HomeTime();
1.1188 +
1.1189 + FOREVER
1.1190 + {
1.1191 + TInt pos=0;
1.1192 + file.Seek(ESeekStart,pos);
1.1193 + for(TInt ii=0;ii<maxReadCount;ii++)
1.1194 + {
1.1195 + r = file.Read(DataBuf,aReadBlockSize);
1.1196 + test_KErrNone(r);
1.1197 +#if defined(_DEBUG)
1.1198 + for(TInt jj=0;jj<DataBuf.Size();jj++)
1.1199 + {
1.1200 + if (DataBuf[jj] != ((jj+ii*aReadBlockSize)%256))
1.1201 + {
1.1202 + test.Printf(_L("len %d size %d jj %d ii %d"), DataBuf.Length(), DataBuf.Size(), jj, ii);
1.1203 + test(0);
1.1204 + }
1.1205 +// test(DataBuf[jj] == ((jj+ii*aReadBlockSize)%256) );
1.1206 + }
1.1207 +#endif
1.1208 + if (reqStat!=KRequestPending)
1.1209 + {
1.1210 + endTime.HomeTime();
1.1211 +
1.1212 + TInt functionCalls=loopCount*maxReadCount+ii;
1.1213 +// TReal rate = ( TReal32(functionCalls) * TReal32(aReadBlockSize) ) / 10;
1.1214 +// test.Printf(_L("Read %5d byte blocks:\t%11.3f KBytes/s\n"), aReadBlockSize, rate / (KOneK));
1.1215 +
1.1216 + TReal transferRate =
1.1217 + (TReal32(functionCalls) * TReal32(aReadBlockSize)) /
1.1218 + TReal(endTime.MicroSecondsFrom(startTime).Int64()) * TReal(KOneMeg) / TReal(KOneK);
1.1219 + test.Printf(_L("Read %5d byte blocks:\t%11.3f KBytes/s\n"), aReadBlockSize,transferRate);
1.1220 +
1.1221 + timer.Close();
1.1222 + file.Close();
1.1223 +
1.1224 + return;
1.1225 + }
1.1226 + }
1.1227 + loopCount++;
1.1228 + }
1.1229 + }
1.1230 +
1.1231 +LOCAL_C void DoTestFileWrite(TUint aFileMode, TInt aWriteBlockSize)
1.1232 +//
1.1233 +// Do Write benchmark
1.1234 +//
1.1235 + {
1.1236 + DataBuf.SetLength(aWriteBlockSize);
1.1237 + TInt maxWriteCount=KMaxFileSize/aWriteBlockSize;
1.1238 + TInt loopCount=0;
1.1239 +
1.1240 + RFile file;
1.1241 + TInt r = file.Replace(TheFs,_L("WRITETST"),EFileStream | aFileMode);
1.1242 + test (r == KErrNone);
1.1243 +
1.1244 + TTime startTime;
1.1245 + TTime endTime;
1.1246 +
1.1247 + RTimer timer;
1.1248 + timer.CreateLocal();
1.1249 + TRequestStatus reqStat;
1.1250 + timer.After(reqStat,10000000); // After 10 secs
1.1251 + startTime.HomeTime();
1.1252 +
1.1253 +
1.1254 +
1.1255 + FOREVER
1.1256 + {
1.1257 + TInt pos=0;
1.1258 + file.Seek(ESeekStart,pos);
1.1259 + for(TInt ii=0;ii<maxWriteCount;ii++)
1.1260 + {
1.1261 + r = file.Write(DataBuf);
1.1262 + test_KErrNone(r);
1.1263 + if (reqStat!=KRequestPending)
1.1264 + {
1.1265 +
1.1266 +// TReal rate = (TReal32(functionCalls) * TReal32(aWriteBlockSize)) / 10;
1.1267 +// test.Printf(_L("Write %5d byte blocks:\t%11.3f KBytes/s\n"), aWriteBlockSize, rate / (KOneK));
1.1268 +
1.1269 + r = file.Flush();
1.1270 + test_KErrNone(r);
1.1271 +
1.1272 + endTime.HomeTime();
1.1273 +
1.1274 + TInt functionCalls=loopCount*maxWriteCount+ii;
1.1275 + TReal transferRate =
1.1276 + (TReal32(functionCalls) * TReal32(aWriteBlockSize)) /
1.1277 + TReal(endTime.MicroSecondsFrom(startTime).Int64()) * TReal(KOneMeg) / TReal(KOneK);
1.1278 + test.Printf(_L("Write %5d byte blocks:\t%11.3f KBytes/s\n"), aWriteBlockSize,transferRate);
1.1279 +
1.1280 + file.Close();
1.1281 + timer.Close();
1.1282 + TInt r=TheFs.Delete(_L("WRITETST"));
1.1283 + test_KErrNone(r);
1.1284 + return;
1.1285 + }
1.1286 + }
1.1287 + loopCount++;
1.1288 + }
1.1289 + }
1.1290 +
1.1291 +LOCAL_C void TestFileRead(TUint aFileMode)
1.1292 +//
1.1293 +// Benchmark read method
1.1294 +//
1.1295 + {
1.1296 +
1.1297 +// ClearSessionDirectory();
1.1298 + test.Next(_L("Benchmark read method"));
1.1299 +// test.Printf(_L("aFileMode %08X\n"), aFileMode);
1.1300 + PrintFileMode(aFileMode);
1.1301 +
1.1302 +// Create test data
1.1303 + TBuf8<1024> testdata(1024);
1.1304 + for (TInt i=0;i<testdata.MaxSize();i++)
1.1305 + testdata[i]=TText8(i%256);
1.1306 +
1.1307 + // create & fill the file
1.1308 + RFile file;
1.1309 + TInt r=file.Replace(TheFs,_L("READTEST.XXX"),EFileStream | aFileMode);
1.1310 + test_KErrNone(r);
1.1311 +
1.1312 + test.Printf(_L("Creating test file....."));
1.1313 + TInt count=KMaxFileSize/testdata.Length();
1.1314 + while (count--)
1.1315 + file.Write(testdata);
1.1316 + file.Close();
1.1317 + test.Printf(_L("done.\n"));
1.1318 +
1.1319 +#ifdef SYMBIAN_TEST_EXTENDED_BUFFER_SIZES
1.1320 +
1.1321 + DoTestFileRead(aFileMode, 1);
1.1322 + DoTestFileRead(aFileMode, 2);
1.1323 + DoTestFileRead(aFileMode, 4);
1.1324 + DoTestFileRead(aFileMode, 8);
1.1325 + DoTestFileRead(aFileMode, 16);
1.1326 + DoTestFileRead(aFileMode, 32);
1.1327 + DoTestFileRead(aFileMode, 64);
1.1328 + DoTestFileRead(aFileMode, 128);
1.1329 + DoTestFileRead(aFileMode, 256);
1.1330 + DoTestFileRead(aFileMode, 512);
1.1331 + DoTestFileRead(aFileMode, 1024);
1.1332 + DoTestFileRead(aFileMode, 2048);
1.1333 + DoTestFileRead(aFileMode, 4096);
1.1334 + DoTestFileRead(aFileMode, 8192);
1.1335 + DoTestFileRead(aFileMode, 16384);
1.1336 + DoTestFileRead(aFileMode, 32768);
1.1337 + DoTestFileRead(aFileMode, 65536);
1.1338 + DoTestFileRead(aFileMode, 131072);
1.1339 +#else
1.1340 +//TheFs.SetDebugRegister(KCACHE);
1.1341 + DoTestFileRead(aFileMode, 1);
1.1342 + DoTestFileRead(aFileMode, 16);
1.1343 + DoTestFileRead(aFileMode, 512);
1.1344 +//TheFs.SetDebugRegister(0);
1.1345 + DoTestFileRead(aFileMode, 4 * 1024);
1.1346 + DoTestFileRead(aFileMode, 32 * 1024);
1.1347 + DoTestFileRead(aFileMode, 64 * 1024);
1.1348 + DoTestFileRead(aFileMode, 128 * 1024);
1.1349 + DoTestFileRead(aFileMode, 256 * 1024);
1.1350 +#endif
1.1351 +
1.1352 + r=TheFs.Delete(_L("READTEST.XXX"));
1.1353 +
1.1354 +
1.1355 +
1.1356 + test_KErrNone(r);
1.1357 + }
1.1358 +
1.1359 +
1.1360 +LOCAL_C void TestFileWrite(TUint aFileMode)
1.1361 +//
1.1362 +// Benchmark write method
1.1363 +//
1.1364 + {
1.1365 +// ClearSessionDirectory();
1.1366 + test.Next(_L("Benchmark write method"));
1.1367 +// test.Printf(_L("aFileMode %08X\n"), aFileMode);
1.1368 + PrintFileMode(aFileMode);
1.1369 +
1.1370 +
1.1371 +// RFile file;
1.1372 +// TInt r = file.Replace(TheFs,_L("WRITETST"),EFileStream | aFileMode);
1.1373 +// test_KErrNone(r);
1.1374 +
1.1375 +
1.1376 +#ifdef SYMBIAN_TEST_EXTENDED_BUFFER_SIZES
1.1377 + DoTestFileWrite(aFileMode, 1);
1.1378 + DoTestFileWrite(aFileMode, 2);
1.1379 + DoTestFileWrite(aFileMode, 4);
1.1380 + DoTestFileWrite(aFileMode, 8);
1.1381 + DoTestFileWrite(aFileMode, 16);
1.1382 + DoTestFileWrite(aFileMode, 32);
1.1383 + DoTestFileWrite(aFileMode, 64);
1.1384 + DoTestFileWrite(aFileMode, 128);
1.1385 + DoTestFileWrite(aFileMode, 256);
1.1386 + DoTestFileWrite(aFileMode, 512);
1.1387 + DoTestFileWrite(aFileMode, 1024);
1.1388 + DoTestFileWrite(aFileMode, 2048);
1.1389 + DoTestFileWrite(aFileMode, 4096);
1.1390 + DoTestFileWrite(aFileMode, 8192);
1.1391 + DoTestFileWrite(aFileMode, 16384);
1.1392 + DoTestFileWrite(aFileMode, 32768);
1.1393 + DoTestFileWrite(aFileMode, 65536);
1.1394 + DoTestFileWrite(aFileMode, 131072);
1.1395 +#else
1.1396 + DoTestFileWrite(aFileMode, 1);
1.1397 + DoTestFileWrite(aFileMode, 16);
1.1398 + DoTestFileWrite(aFileMode, 512);
1.1399 + DoTestFileWrite(aFileMode, 4 * 1024);
1.1400 + DoTestFileWrite(aFileMode, 32 * 1024);
1.1401 + DoTestFileWrite(aFileMode, 64 * 1024);
1.1402 + DoTestFileWrite(aFileMode, 128 * 1024);
1.1403 + DoTestFileWrite(aFileMode, 256 * 1024);
1.1404 +#endif
1.1405 + }
1.1406 +
1.1407 +enum CommandId {
1.1408 + CMD_NO_COMMAND,
1.1409 + CMD_HELP,
1.1410 + CMD_DISPLAY_CACHE_FLAGS,
1.1411 + CMD_WRITE_CACHE_FLAGS,
1.1412 + CMD_PERFORMANCE_TEST,
1.1413 + CMD_MANUAL_TEST
1.1414 +};
1.1415 +
1.1416 +
1.1417 +class CommandLineOption {
1.1418 +public:
1.1419 + CommandLineOption(const TPtrC &s, CommandId i) : str(s), id(i) { }
1.1420 +
1.1421 + const TPtrC str;
1.1422 + CommandId id;
1.1423 +
1.1424 +private:
1.1425 + CommandLineOption() { }
1.1426 +};
1.1427 +
1.1428 +// Lists of command line options
1.1429 +static const CommandLineOption commandList[] = {
1.1430 + CommandLineOption(_L("-help"), CMD_HELP),
1.1431 + CommandLineOption(_L("-h"), CMD_HELP),
1.1432 + CommandLineOption(_L("-?"), CMD_HELP),
1.1433 + CommandLineOption(_L("/?"), CMD_HELP),
1.1434 + CommandLineOption(_L("-d"), CMD_DISPLAY_CACHE_FLAGS),
1.1435 + CommandLineOption(_L("-w"), CMD_WRITE_CACHE_FLAGS),
1.1436 + CommandLineOption(_L("-p"), CMD_PERFORMANCE_TEST),
1.1437 + CommandLineOption(_L("-m"), CMD_MANUAL_TEST),
1.1438 +};
1.1439 +
1.1440 +
1.1441 +
1.1442 +LOCAL_C void printHelp() {
1.1443 + test.Printf(_L("Option Explanation\r\n"));
1.1444 + test.Printf(_L("-help Print this text\r\n"));
1.1445 + test.Printf(_L("-d Display cache flags\n"));
1.1446 + test.Printf(_L("-p Performance test\n"));
1.1447 +}
1.1448 +
1.1449 +
1.1450 +
1.1451 +/////////////////////////////////////////////////////////////////////////////
1.1452 +// Function:
1.1453 +// bool parseCommandLine()
1.1454 +//
1.1455 +// Parameters:
1.1456 +// -
1.1457 +//
1.1458 +// Return value:
1.1459 +// true if command line options was correct, false if any command was
1.1460 +// invalid
1.1461 +//
1.1462 +// Purpose:
1.1463 +// Parses the command line
1.1464 +//
1.1465 +/////////////////////////////////////////////////////////////////////////////
1.1466 +
1.1467 +//TBuf<512> commandLine;
1.1468 +
1.1469 +
1.1470 +LOCAL_C bool ParseCommandLine( const TDesC& aCommand )
1.1471 + {
1.1472 + TLex lex(aCommand);
1.1473 + TInt tokenCount = 0;
1.1474 +
1.1475 + gDriveToTest='C';
1.1476 + gRunTests = ETrue;
1.1477 +
1.1478 + for (TPtrC token=lex.NextToken(); token.Length() != 0;token.Set(lex.NextToken()))
1.1479 + {
1.1480 + tokenCount++;
1.1481 +
1.1482 + //
1.1483 + // Search the list of commands for a match.
1.1484 + //
1.1485 + CommandId commandId = CMD_NO_COMMAND;
1.1486 + for (TUint i = 0; i < sizeof commandList / sizeof commandList[0]; i++)
1.1487 + {
1.1488 + if (token.CompareF(commandList[i].str) == 0)
1.1489 + {
1.1490 + //
1.1491 + // Found a matching string
1.1492 + //
1.1493 + commandId = commandList[i].id;
1.1494 + break;
1.1495 + }
1.1496 + }
1.1497 +
1.1498 + switch (commandId)
1.1499 + {
1.1500 + case CMD_NO_COMMAND:
1.1501 + {
1.1502 + TFileName thisfile=RProcess().FileName();
1.1503 + if (token.MatchF(thisfile)==0)
1.1504 + {
1.1505 + token.Set(lex.NextToken());
1.1506 + }
1.1507 + test.Printf(_L("CLP=%S\n"),&token);
1.1508 +
1.1509 + TChar ch = token[0];
1.1510 + if (ch.IsAlpha())
1.1511 + {
1.1512 + if(token.Length()!=0)
1.1513 + {
1.1514 + gDriveToTest=token[0];
1.1515 + gDriveToTest.UpperCase();
1.1516 + }
1.1517 + else
1.1518 + gDriveToTest='C';
1.1519 + lex.NextToken();
1.1520 + }
1.1521 + }
1.1522 + break;
1.1523 +
1.1524 + case CMD_HELP:
1.1525 + printHelp();
1.1526 + gRunTests = EFalse;
1.1527 + break;
1.1528 +
1.1529 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.1530 + case CMD_WRITE_CACHE_FLAGS:
1.1531 + {
1.1532 + token.Set(lex.NextToken());
1.1533 + if (token.Length() == 0) {
1.1534 + printHelp();
1.1535 + return false;
1.1536 + }
1.1537 + //
1.1538 + // Extract flags (in hex) from next token.
1.1539 + //
1.1540 + TPtrC numStr(token);
1.1541 + TUint val;
1.1542 + TInt r = TLex(numStr).Val(val, EHex);
1.1543 + if (r != KErrNone) {
1.1544 + printHelp();
1.1545 + return false;
1.1546 + }
1.1547 + gDriveCacheFlags = TFileCacheFlags(val);
1.1548 + gWriteCacheFlags = ETrue;
1.1549 + gRunTests = EFalse;
1.1550 + break;
1.1551 + }
1.1552 +
1.1553 + case CMD_DISPLAY_CACHE_FLAGS:
1.1554 + gDisplayCacheFlags = ETrue;
1.1555 + gRunTests = EFalse;
1.1556 + break;
1.1557 +#endif
1.1558 + case CMD_PERFORMANCE_TEST:
1.1559 + gRunPerformanceTests = ETrue;
1.1560 + gRunUnitTests = EFalse;
1.1561 + break;
1.1562 +
1.1563 + case CMD_MANUAL_TEST:
1.1564 + gRunManualTests = ETrue;
1.1565 + gRunUnitTests = EFalse;
1.1566 + break;
1.1567 +
1.1568 + default:
1.1569 + test.Printf(_L("Sorry, command option '%S' not implemented\n"),
1.1570 + &token);
1.1571 + break;
1.1572 + }
1.1573 +
1.1574 + }
1.1575 + return true;
1.1576 +}
1.1577 +
1.1578 +
1.1579 +LOCAL_C TBool parseCommandLine() {
1.1580 + //
1.1581 + // Loop through all tokens in the command line
1.1582 + //
1.1583 + TInt cmdLineLen = User::CommandLineLength();
1.1584 + HBufC* cmdLineBuf = HBufC::New( cmdLineLen );
1.1585 + if( !cmdLineBuf )
1.1586 + {
1.1587 + return false;
1.1588 + }
1.1589 + TPtr ptr = cmdLineBuf->Des();
1.1590 + User::CommandLine(ptr);
1.1591 +
1.1592 + bool err = ParseCommandLine( *cmdLineBuf );
1.1593 + delete cmdLineBuf;
1.1594 + return err;
1.1595 + }
1.1596 +
1.1597 +GLDEF_C void CallTestsL()
1.1598 +//
1.1599 +// Do tests relative to the session path
1.1600 +//
1.1601 + {
1.1602 + TestsInit();
1.1603 +
1.1604 + TVolumeInfo volInfo;
1.1605 + TInt r = TheFs.Volume(volInfo, gDrive);
1.1606 + test (r == KErrNone);
1.1607 +
1.1608 + TFullName extName;
1.1609 + r = TheFs.ExtensionName(extName,gDrive, 0);
1.1610 + if (r == KErrNone)
1.1611 + {
1.1612 + test.Printf(_L("File system extension present (%S)\n"), &extName);
1.1613 + }
1.1614 +
1.1615 + if ((volInfo.iDrive.iType == EMediaRam) ||
1.1616 + ((gDriveCacheFlags & (EFileCacheReadEnabled | EFileCacheReadOn)) == 0))
1.1617 + {
1.1618 + if (gRunPerformanceTests)
1.1619 + {
1.1620 + TestFileRead(EFileReadDirectIO);
1.1621 + TestFileWrite(EFileWriteDirectIO);
1.1622 + }
1.1623 + TestsEnd();
1.1624 + return;
1.1625 + }
1.1626 +
1.1627 + if (gRunUnitTests)
1.1628 + UnitTests();
1.1629 +
1.1630 + if (gRunManualTests)
1.1631 + {
1.1632 + ManualTests();
1.1633 + }
1.1634 +
1.1635 + if (gRunPerformanceTests)
1.1636 + {
1.1637 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.1638 + // turn OFF lock failure mode
1.1639 + TBool simulatelockFailureMode = EFalse;
1.1640 + r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode);
1.1641 + test (r == KErrNone);
1.1642 +#endif
1.1643 +
1.1644 + TestFileRead(EFileReadDirectIO);
1.1645 + if (gDriveCacheFlags & (EFileCacheReadEnabled | EFileCacheReadOn))
1.1646 + {
1.1647 + TestFileRead(EFileReadBuffered | EFileReadAheadOff);
1.1648 + TestFileRead(EFileReadBuffered | EFileReadAheadOn);
1.1649 + }
1.1650 +
1.1651 + TestFileWrite(EFileWriteDirectIO);
1.1652 +
1.1653 + if (gDriveCacheFlags & (EFileCacheWriteEnabled | EFileCacheWriteOn))
1.1654 + TestFileWrite(EFileWriteBuffered);
1.1655 +
1.1656 +
1.1657 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.1658 + // turn lock failure mode back ON (if enabled)
1.1659 + simulatelockFailureMode = ETrue;
1.1660 + r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode);
1.1661 + test (r == KErrNone);
1.1662 +#endif
1.1663 + } // if (gRunPerformanceTests)
1.1664 +
1.1665 + TestsEnd();
1.1666 + }
1.1667 +
1.1668 +
1.1669 +
1.1670 +LOCAL_C void DoTests(TInt aDrive)
1.1671 +//
1.1672 +// Do testing on aDrive
1.1673 +//
1.1674 + {
1.1675 +
1.1676 + SetSessionPath(aDrive);
1.1677 +
1.1678 +// !!! Disable platform security tests until we get the new APIs
1.1679 +// if(User::Capability() & KCapabilityRoot)
1.1680 +// CheckMountLFFS(TheFs,driveLetter);
1.1681 +
1.1682 + User::After(1000000);
1.1683 +
1.1684 + TInt r=TheFs.MkDirAll(gSessionPath);
1.1685 + test_Value(r, r == KErrNone || r == KErrAlreadyExists);
1.1686 + TheFs.ResourceCountMarkStart();
1.1687 +
1.1688 + TRAP(r,CallTestsL());
1.1689 + test_KErrNone(r);
1.1690 +
1.1691 + TheFs.ResourceCountMarkEnd();
1.1692 + }
1.1693 +
1.1694 +
1.1695 +void Format(TInt aDrive)
1.1696 +//
1.1697 +// Format current drive
1.1698 +//
1.1699 + {
1.1700 +
1.1701 + test.Next(_L("Format"));
1.1702 + TBuf<4> driveBuf=_L("?:\\");
1.1703 + driveBuf[0]=(TText)(aDrive+'A');
1.1704 + RFormat format;
1.1705 + TInt count;
1.1706 + TInt r=format.Open(TheFs,driveBuf,EQuickFormat,count);
1.1707 + //TInt r=format.Open(TheFs,driveBuf,EFullFormat,count);
1.1708 + test.Printf(_L("RFormat::Open() returned %d\n"), r);
1.1709 + test_KErrNone(r);
1.1710 + while(count)
1.1711 + {
1.1712 + TInt r=format.Next(count);
1.1713 + test_KErrNone(r);
1.1714 + }
1.1715 + format.Close();
1.1716 + }
1.1717 +
1.1718 +GLDEF_C TInt E32Main()
1.1719 +//
1.1720 +// Test with drive nearly full
1.1721 +//
1.1722 + {
1.1723 +
1.1724 + CTrapCleanup* cleanup;
1.1725 + cleanup=CTrapCleanup::New();
1.1726 +
1.1727 + __UHEAP_MARK;
1.1728 +
1.1729 + TBool parseOk = parseCommandLine();
1.1730 + if (!parseOk)
1.1731 + User::Leave(KErrNotSupported);
1.1732 +
1.1733 +
1.1734 + TInt r = TheFs.Connect();
1.1735 + test_KErrNone(r);
1.1736 +
1.1737 + r=TheFs.CharToDrive(gDriveToTest,gDrive);
1.1738 + test_KErrNone(r);
1.1739 +
1.1740 +#if !defined(__WINS__)
1.1741 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.1742 + test.Start(_L("Check that the rom is paged"));
1.1743 + TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
1.1744 + if (romHeader->iPageableRomStart != NULL)
1.1745 + {
1.1746 + test.Printf(_L("ROM is paged\n"));
1.1747 + gRomPaged = ETrue;
1.1748 + }
1.1749 +#endif
1.1750 +#endif
1.1751 +
1.1752 + // Get the TFileCacheFlags for this drive
1.1753 + r = TheFs.Volume(gVolInfo, gDrive);
1.1754 + if (r == KErrNotReady)
1.1755 + {
1.1756 + TDriveInfo info;
1.1757 + TInt err = TheFs.Drive(info,gDrive);
1.1758 + test_KErrNone(err);
1.1759 + if (info.iType == EMediaNotPresent)
1.1760 + test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)gDriveToTest);
1.1761 + else
1.1762 + 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)gDriveToTest);
1.1763 + }
1.1764 + else if (r == KErrCorrupt)
1.1765 + {
1.1766 + test.Printf(_L("%c: Media corruption; previous test may have aborted; else, check hardware\n"), (TUint)gDriveToTest);
1.1767 + }
1.1768 + test_KErrNone(r);
1.1769 + gDriveCacheFlags = gVolInfo.iFileCacheFlags;
1.1770 + test.Printf(_L("DriveCacheFlags for drive %C = %08X\n"), (TInt) gDriveToTest, gDriveCacheFlags);
1.1771 +
1.1772 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.1773 + PrintFileCacheConfig(gFileCacheConfig, gDrive);
1.1774 +
1.1775 + if (gDisplayCacheFlags)
1.1776 + {
1.1777 + test.Printf(_L("Press any key...\n"));
1.1778 + test.Getch();
1.1779 + }
1.1780 +
1.1781 + if (gWriteCacheFlags)
1.1782 + {
1.1783 + test.Printf(_L("Writing DriveCacheFlags for drive %C = %08X\n"), (TInt) gDriveToTest, gDriveCacheFlags);
1.1784 + r = controlIo(TheFs,gDrive, KControlIoFileCacheFlagsWrite, gDriveCacheFlags);
1.1785 + test (r == KErrNone);
1.1786 + }
1.1787 +#endif
1.1788 +
1.1789 + if (gRunTests)
1.1790 + {
1.1791 + test.Title();
1.1792 +
1.1793 +
1.1794 + test.Start(_L("Starting tests..."));
1.1795 +
1.1796 + if ((gVolInfo.iDrive.iMediaAtt & KMediaAttFormattable))
1.1797 + Format(gDrive);
1.1798 +
1.1799 +//TheFs.SetDebugRegister(KCACHE);
1.1800 + DoTests(gDrive);
1.1801 +//TheFs.SetDebugRegister(0);
1.1802 + test.End();
1.1803 +// }
1.1804 + }
1.1805 +
1.1806 +#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
1.1807 + TFileCacheStats fileCacheStats;
1.1808 + PrintFileCacheStats(fileCacheStats);
1.1809 +#endif
1.1810 +
1.1811 + TheFs.Close();
1.1812 + test.Close();
1.1813 + __UHEAP_MARKEND;
1.1814 + delete cleanup;
1.1815 + return(KErrNone);
1.1816 + }