|
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // f32test\server\t_filecache.cpp |
|
15 // |
|
16 // |
|
17 #define __E32TEST_EXTENSION__ |
|
18 #include <f32file.h> |
|
19 #include <e32test.h> |
|
20 #include <e32svr.h> |
|
21 #include <f32dbg.h> |
|
22 #include "t_server.h" |
|
23 #include <e32twin.h> |
|
24 #include <e32rom.h> |
|
25 |
|
26 |
|
27 //---------------------------------------------------------------------------------------------- |
|
28 //! @SYMTestCaseID PBASE-T_FILECACHE-0189 |
|
29 //! @SYMTestType UT |
|
30 //! @SYMPREQ PREQ914 |
|
31 //! @SYMTestCaseDesc Unit tests for fair scheduling, read caching and lazy writing |
|
32 //! @SYMTestActions 0 setup the environment to execute the tests |
|
33 //! 1 Reads a file with different blocksizes |
|
34 //! 2 Write a file with different blocksizes |
|
35 //! 3 Small reads while controlling the cache |
|
36 //! 4 Read operations with and without read ahead |
|
37 //! 5 Write operations with write buffer |
|
38 //! @SYMTestExpectedResults finishes if the implementation of PREQ914 behaves as expected, panics otherwise |
|
39 //! @SYMTestPriority High |
|
40 //! @SYMTestStatus Critical |
|
41 //---------------------------------------------------------------------------------------------- |
|
42 |
|
43 |
|
44 //#define SYMBIAN_TEST_EXTENDED_BUFFER_SIZES |
|
45 |
|
46 |
|
47 GLDEF_D RTest test(_L("T_FILECACHE")); |
|
48 |
|
49 GLDEF_D RFs TheFs; |
|
50 GLDEF_D TChar gDriveToTest; |
|
51 GLDEF_D TInt gDrive; |
|
52 GLDEF_D TFileName gSessionPath; |
|
53 |
|
54 GLDEF_D TVolumeInfo gVolInfo; // volume info for current drive |
|
55 GLDEF_D TFileCacheFlags gDriveCacheFlags = TFileCacheFlags(0); |
|
56 |
|
57 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
58 static TFileCacheConfig gFileCacheConfig; |
|
59 static TBool gDisplayCacheFlags = EFalse; |
|
60 static TBool gWriteCacheFlags = EFalse; |
|
61 static TBool gRomPaged = EFalse; |
|
62 #endif |
|
63 static TBool gRunTests = ETrue; |
|
64 static TBool gRunUnitTests = ETrue; |
|
65 static TBool gRunPerformanceTests = EFalse; |
|
66 static TBool gRunManualTests = EFalse; |
|
67 |
|
68 |
|
69 LOCAL_D TInt KMaxFileSize = 768 * 1024; |
|
70 |
|
71 // Chosing a file size of 128K ensures entire file will be cached |
|
72 //LOCAL_D TInt KMaxFileSize = 128 * 1024; |
|
73 |
|
74 LOCAL_D TBuf8<256*1024> DataBuf; |
|
75 |
|
76 const TInt KBufSize = 513 * 1024 - 16; |
|
77 HBufC8* gBuf = NULL; |
|
78 |
|
79 |
|
80 LOCAL_D TPtr8 gBufPtr(NULL, 0); |
|
81 |
|
82 const TReal KOneK = 1024; |
|
83 const TReal KOneMeg = 1024 * KOneK; |
|
84 |
|
85 const TInt KSegmentSize = 4096; |
|
86 const TInt KSegmentSizeMask = (4096-1); |
|
87 |
|
88 GLDEF_D template <class C> |
|
89 GLDEF_C TInt controlIo(RFs &fs, TInt drv, TInt fkn, C &c) |
|
90 { |
|
91 TPtr8 ptrC((TUint8 *)&c, sizeof(C), sizeof(C)); |
|
92 |
|
93 TInt r = fs.ControlIo(drv, fkn, ptrC); |
|
94 |
|
95 return r; |
|
96 } |
|
97 |
|
98 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
99 void PrintFileCacheStats(TFileCacheStats& fileCacheStats, TBool aDisplay = ETrue) |
|
100 { |
|
101 TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
102 test_KErrNone(r); |
|
103 if (!aDisplay) |
|
104 return; |
|
105 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"), |
|
106 fileCacheStats.iFreeCount, fileCacheStats.iUsedCount, fileCacheStats.iAllocatedSegmentCount,fileCacheStats.iLockedSegmentCount,fileCacheStats.iFilesOnClosedQueue, fileCacheStats.iHoleCount, fileCacheStats.iCommitFailureCount, fileCacheStats.iLockFailureCount); |
|
107 test.Printf(_L("File cache: iUncachedPacketsRead %d iUncachedBytesRead %d iUncachedPacketsWritten %d iUncachedBytesWritten %d\n"), |
|
108 fileCacheStats.iUncachedPacketsRead, |
|
109 fileCacheStats.iUncachedBytesRead, |
|
110 fileCacheStats.iUncachedPacketsWritten, |
|
111 fileCacheStats.iUncachedBytesWritten); |
|
112 } |
|
113 |
|
114 void PrintFileCacheConfig(TFileCacheConfig& aFileCacheConfig, TBool aDisplay = ETrue) |
|
115 { |
|
116 TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheConfig, aFileCacheConfig); |
|
117 test (r == KErrNone); |
|
118 if (!aDisplay) |
|
119 return; |
|
120 |
|
121 test.Printf(_L("File cache:\nDrive %c\nFlags %08X\nFileCacheReadAsync %d\nFairSchedulingLen %d\nCacheSize %d\nMaxReadAheadLen %d\nClosedFileKeepAliveTime %d\nDirtyDataFlushTime %d"), |
|
122 aFileCacheConfig.iDrive + 'A', |
|
123 aFileCacheConfig.iFlags, |
|
124 aFileCacheConfig.iFileCacheReadAsync, |
|
125 aFileCacheConfig.iFairSchedulingLen, |
|
126 aFileCacheConfig.iCacheSize, |
|
127 aFileCacheConfig.iMaxReadAheadLen, |
|
128 aFileCacheConfig.iClosedFileKeepAliveTime, |
|
129 aFileCacheConfig.iDirtyDataFlushTime); |
|
130 |
|
131 } |
|
132 |
|
133 void TestDirtyDataWrittenToDisk(TFileCacheStats& fileCacheStats) |
|
134 { |
|
135 test.Next(_L("test dirty data has been written to disk")); |
|
136 // wait a maximum of double KDefaultDirtyDataFlushTime for dirty data to be flushed |
|
137 const TInt KWaitTime = 250; // 250 milisecs |
|
138 for (TInt n=0; n<(gFileCacheConfig.iDirtyDataFlushTime/1000)<<1 ; n+= KWaitTime) |
|
139 { |
|
140 test.Printf(_L("After %d milisecs : "), n ); |
|
141 PrintFileCacheStats(fileCacheStats); |
|
142 User::After(KWaitTime * 1000); // wait 100 ms |
|
143 if (fileCacheStats.iLockedSegmentCount == 0) |
|
144 break; |
|
145 } |
|
146 PrintFileCacheStats(fileCacheStats); |
|
147 test(fileCacheStats.iLockedSegmentCount == 0); |
|
148 } |
|
149 #endif |
|
150 |
|
151 void TestsInit() |
|
152 { |
|
153 gBuf = HBufC8::NewL(KBufSize); |
|
154 test(gBuf!=NULL); |
|
155 gBufPtr.Set(gBuf->Des()); |
|
156 } |
|
157 void TestsEnd() |
|
158 { |
|
159 delete gBuf; |
|
160 gBuf = NULL; |
|
161 } |
|
162 |
|
163 LOCAL_C void SetSessionPath(TInt aDrive) |
|
164 { |
|
165 gSessionPath=_L("?:\\F32-TST\\"); |
|
166 TChar driveLetter; |
|
167 TInt r=TheFs.DriveToChar(aDrive,driveLetter); |
|
168 test_KErrNone(r); |
|
169 gSessionPath[0]=(TText)driveLetter; |
|
170 r=TheFs.SetSessionPath(gSessionPath); |
|
171 test_KErrNone(r); |
|
172 } |
|
173 |
|
174 LOCAL_C void PrintFileMode(TUint aFileMode) |
|
175 { |
|
176 TBuf<80> buf; |
|
177 |
|
178 buf.Format(_L("FileMode = %08X"), aFileMode); |
|
179 |
|
180 if (aFileMode & EFileWriteBuffered) |
|
181 buf.Append(_L(", EFileWriteBuffered")); |
|
182 |
|
183 if (aFileMode & EFileWriteDirectIO) |
|
184 buf.Append(_L(", EFileWriteDirectIO")); |
|
185 |
|
186 if (aFileMode & EFileReadBuffered) |
|
187 buf.Append(_L(", EFileReadBuffered")); |
|
188 |
|
189 if (aFileMode & EFileReadDirectIO) |
|
190 buf.Append(_L(", EFileReadDirectIO")); |
|
191 |
|
192 if (aFileMode & EFileReadAheadOn) |
|
193 buf.Append(_L(", EFileReadAheadOn")); |
|
194 |
|
195 if (aFileMode & EFileReadAheadOff) |
|
196 buf.Append(_L(", EFileReadAheadOff")); |
|
197 |
|
198 buf.Append(_L("\n")); |
|
199 test.Printf(buf); |
|
200 } |
|
201 |
|
202 void FillBuffer(TDes8& aBuffer, TInt aLength) |
|
203 { |
|
204 test (aBuffer.MaxLength() >= aLength); |
|
205 for(TInt i=0; i<aLength; i+=2) |
|
206 { |
|
207 aBuffer[i]=(TUint8) (i >> 8); |
|
208 aBuffer[i+1]=(TUint8) i; |
|
209 } |
|
210 } |
|
211 |
|
212 void TestBufferFail(TDes8& aBuffer, TInt aPos, TInt aLength) |
|
213 { |
|
214 test.Printf(_L("TestBuffer failed at pos %d len %d\n"), aPos, aLength); |
|
215 |
|
216 #define PRINTCH(ch) ((ch >= 0x20 && ch < 0x7F)?ch:' ') |
|
217 TInt startPos = Max(0, aPos - 64); |
|
218 TInt endPos = startPos + 64; |
|
219 |
|
220 for(TInt n=startPos; n<=endPos; n+=16) |
|
221 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]"), |
|
222 //&aBuffer[aPos+n], |
|
223 n, |
|
224 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], |
|
225 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])); |
|
226 |
|
227 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
228 TInt x; |
|
229 TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheDump, x); |
|
230 test_KErrNone(r); |
|
231 #endif |
|
232 test (0); |
|
233 } |
|
234 |
|
235 void TestBuffer(TDes8& aBuffer, TInt aPos, TInt aLength) |
|
236 { |
|
237 TInt pos = aPos; |
|
238 for(TInt i=0; i<aLength; i++, pos++) |
|
239 { |
|
240 if (pos & 1) |
|
241 { |
|
242 if (aBuffer[pos] != (TUint8) pos-1) |
|
243 TestBufferFail(aBuffer, pos, aLength); |
|
244 } |
|
245 else |
|
246 { |
|
247 if (aBuffer[pos] != (TUint8) (pos >> 8)) |
|
248 TestBufferFail(aBuffer, pos, aLength); |
|
249 } |
|
250 } |
|
251 } |
|
252 |
|
253 |
|
254 LOCAL_C void UnitTests() |
|
255 // |
|
256 // Test read file handling. |
|
257 // |
|
258 { |
|
259 |
|
260 test.Start(_L("File cache read and write unit tests")); |
|
261 |
|
262 //TheFs.SetDebugRegister(KCACHE); |
|
263 |
|
264 RFile f; |
|
265 TInt r; |
|
266 TInt pos; |
|
267 TInt len; |
|
268 TInt testNum; |
|
269 |
|
270 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
271 TBool simulatelockFailureMode; |
|
272 TFileCacheStats fileCacheStats; |
|
273 r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
274 test (r == KErrNone); |
|
275 test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue); |
|
276 test(fileCacheStats.iFilesOnClosedQueue == 0); |
|
277 #endif |
|
278 |
|
279 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
280 // turn OFF lock failure mode |
|
281 simulatelockFailureMode = EFalse; |
|
282 r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); |
|
283 test (r == KErrNone); |
|
284 #endif |
|
285 |
|
286 TFileName testFile = _L("TEST.BIN"); |
|
287 |
|
288 //********************************** |
|
289 // Test Read-Modify-Write |
|
290 //********************************** |
|
291 test.Next(_L("Test read-modify-write")); |
|
292 gBufPtr.SetLength(KBufSize); |
|
293 FillBuffer(gBufPtr, KBufSize); |
|
294 TestBuffer(gBufPtr, 0,KBufSize); |
|
295 TPtrC8 writePtr; |
|
296 TPtr8 readPtr(gBuf->Des()); |
|
297 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
298 TInt uncachedBytesRead; |
|
299 TInt uncachedPacketsRead; |
|
300 #endif |
|
301 |
|
302 // create an empty file, so that any writes overlapping segemt boundaries |
|
303 // need a read first |
|
304 // create a test file using directIO and then re-open it in buffered mode, |
|
305 // so that any writes overlapping segemt boundaries need a read first |
|
306 r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteDirectIO); |
|
307 test_KErrNone(r); |
|
308 writePtr.Set(gBuf->Des()); |
|
309 r = f.Write(0, writePtr); |
|
310 test_KErrNone(r); |
|
311 f.Close(); |
|
312 r = f.Open(TheFs, testFile, EFileReadBuffered | EFileWrite | EFileWriteBuffered); |
|
313 test_KErrNone(r); |
|
314 |
|
315 TInt cacheLineLen = 128*1024; |
|
316 |
|
317 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
318 PrintFileCacheStats(fileCacheStats); |
|
319 uncachedBytesRead = fileCacheStats.iUncachedBytesRead; |
|
320 uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead; |
|
321 #endif |
|
322 |
|
323 // write 1 partial segment at offset 0 to 7 in segment |
|
324 test.Next(_L("Test read-modify-write #1")); |
|
325 pos = cacheLineLen*0 + KSegmentSize*2 + 0; |
|
326 len = 7; |
|
327 writePtr.Set(gBuf->Mid(pos, len)); |
|
328 r = f.Write(pos, writePtr, len); |
|
329 test_KErrNone(r); |
|
330 // read back & verify whole segment |
|
331 pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask; |
|
332 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
333 readPtr.SetLength(len); |
|
334 readPtr.FillZ(); |
|
335 r = f.Read(pos, readPtr, len); |
|
336 test_KErrNone(r); |
|
337 TestBuffer(gBufPtr, pos, len); |
|
338 test_KErrNone(r); |
|
339 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
340 PrintFileCacheStats(fileCacheStats); |
|
341 test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize); |
|
342 test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 1); |
|
343 uncachedBytesRead = fileCacheStats.iUncachedBytesRead; |
|
344 uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead; |
|
345 #endif |
|
346 |
|
347 // write 1 partial segment at offset 7 to 4096 in segment |
|
348 test.Next(_L("Test read-modify-write #2")); |
|
349 pos = cacheLineLen*0 + KSegmentSize*3 + 7; |
|
350 len = KSegmentSize - 7; |
|
351 writePtr.Set(gBuf->Mid(pos, len)); |
|
352 r = f.Write(pos, writePtr, len); |
|
353 test_KErrNone(r); |
|
354 // read back & verify whole segment |
|
355 pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask; |
|
356 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
357 readPtr.SetLength(len); |
|
358 readPtr.FillZ(); |
|
359 r = f.Read(pos, readPtr, len); |
|
360 test_KErrNone(r); |
|
361 TestBuffer(gBufPtr, pos, len); |
|
362 test_KErrNone(r); |
|
363 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
364 PrintFileCacheStats(fileCacheStats); |
|
365 test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize); |
|
366 test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 1); |
|
367 uncachedBytesRead = fileCacheStats.iUncachedBytesRead; |
|
368 uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead; |
|
369 #endif |
|
370 |
|
371 // write 1 partial segment at offset 7 to 37 in segment |
|
372 test.Next(_L("Test read-modify-write #3")); |
|
373 pos = cacheLineLen*0 + KSegmentSize*4 + 7; |
|
374 len = 30; |
|
375 writePtr.Set(gBuf->Mid(pos, len)); |
|
376 r = f.Write(pos, writePtr, len); |
|
377 test_KErrNone(r); |
|
378 // read back & verify whole segment |
|
379 pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask; |
|
380 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
381 readPtr.SetLength(len); |
|
382 readPtr.FillZ(); |
|
383 r = f.Read(pos, readPtr, len); |
|
384 test_KErrNone(r); |
|
385 TestBuffer(gBufPtr, pos, len); |
|
386 test_KErrNone(r); |
|
387 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
388 PrintFileCacheStats(fileCacheStats); |
|
389 test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize); |
|
390 test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 1); |
|
391 uncachedBytesRead = fileCacheStats.iUncachedBytesRead; |
|
392 uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead; |
|
393 #endif |
|
394 |
|
395 // write 2 segments, first and last both partial |
|
396 test.Next(_L("Test read-modify-write #4")); |
|
397 pos = cacheLineLen*1 + KSegmentSize*2 + 3; |
|
398 len = KSegmentSize * 1; |
|
399 writePtr.Set(gBuf->Mid(pos, len)); |
|
400 r = f.Write(pos, writePtr, len); |
|
401 test_KErrNone(r); |
|
402 // read back & verify whole segment |
|
403 pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask; |
|
404 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
405 readPtr.SetLength(len); |
|
406 readPtr.FillZ(); |
|
407 r = f.Read(pos, readPtr, len); |
|
408 test_KErrNone(r); |
|
409 TestBuffer(gBufPtr, pos, len); |
|
410 test_KErrNone(r); |
|
411 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
412 PrintFileCacheStats(fileCacheStats); |
|
413 test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize*2); |
|
414 // should read both segments in one read as they are contiguous |
|
415 test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 1); |
|
416 uncachedBytesRead = fileCacheStats.iUncachedBytesRead; |
|
417 uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead; |
|
418 #endif |
|
419 |
|
420 // write 3 segments, first and last both partial |
|
421 test.Next(_L("Test read-modify-write #5")); |
|
422 pos = cacheLineLen*2 + KSegmentSize*2 + 7; |
|
423 len = KSegmentSize * 2; |
|
424 writePtr.Set(gBuf->Mid(pos, len)); |
|
425 r = f.Write(pos, writePtr, len); |
|
426 test_KErrNone(r); |
|
427 // read back & verify whole segment |
|
428 pos&= ~KSegmentSizeMask; len = (len + KSegmentSize-1) & ~KSegmentSizeMask; |
|
429 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
430 readPtr.SetLength(len); |
|
431 readPtr.FillZ(); |
|
432 r = f.Read(pos, readPtr, len); |
|
433 test_KErrNone(r); |
|
434 TestBuffer(gBufPtr, pos, len); |
|
435 test_KErrNone(r); |
|
436 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
437 PrintFileCacheStats(fileCacheStats); |
|
438 test (fileCacheStats.iUncachedBytesRead - uncachedBytesRead == KSegmentSize*2); |
|
439 test (fileCacheStats.iUncachedPacketsRead - uncachedPacketsRead == 2); |
|
440 uncachedBytesRead = fileCacheStats.iUncachedBytesRead; |
|
441 uncachedPacketsRead = fileCacheStats.iUncachedPacketsRead; |
|
442 #endif |
|
443 |
|
444 f.Close(); |
|
445 |
|
446 //************************************************************** |
|
447 // Test dirty data NOT written to disk if continuously writing to a file which fits in tke cache |
|
448 //************************************************************** |
|
449 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
450 test.Printf(_L("Test dirty data NOT written to disk if continuously writing to a file which fits in tke cache...\n")); |
|
451 |
|
452 // flush closed files queue to empty cache |
|
453 test.Printf(_L("Flushing close queue to empty cache...\n")); |
|
454 r = TheFs.ControlIo(gDrive, KControlIoFlushClosedFiles); |
|
455 test_KErrNone(r); |
|
456 |
|
457 r = f.Replace(TheFs, testFile, EFileReadBuffered | EFileWrite | EFileWriteBuffered); |
|
458 test_KErrNone(r); |
|
459 |
|
460 RTimer timer; |
|
461 timer.CreateLocal(); |
|
462 TRequestStatus reqStat; |
|
463 timer.After(reqStat,gFileCacheConfig.iClosedFileKeepAliveTime*3); // write 3 times the flush timer |
|
464 |
|
465 pos = 0; |
|
466 TInt bufLen = 7; |
|
467 TInt maxLockedSegmentCount = 0; |
|
468 while (reqStat == KRequestPending) |
|
469 { |
|
470 bufLen = (bufLen + 1023) & 0x3FFF; |
|
471 len = Min(bufLen, KBufSize - pos); |
|
472 len = Min(len, gFileCacheConfig.iCacheSize-pos); |
|
473 TPtrC8 writePtr = gBuf->Mid(pos, len); |
|
474 r = f.Write(pos, writePtr, len); |
|
475 test_KErrNone(r); |
|
476 pos+= len; |
|
477 TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
478 test_KErrNone(r); |
|
479 // test the locked (i.e. dirty) count always goes up & never down (down would indicate a flush) |
|
480 if (fileCacheStats.iLockedSegmentCount != maxLockedSegmentCount) |
|
481 test.Printf(_L("iLockedSegmentCount %d...\n"), fileCacheStats.iLockedSegmentCount); |
|
482 |
|
483 test(fileCacheStats.iLockedSegmentCount >= maxLockedSegmentCount); |
|
484 maxLockedSegmentCount = Max(maxLockedSegmentCount, fileCacheStats.iLockedSegmentCount); |
|
485 // wrap to start of file |
|
486 if (pos >= gFileCacheConfig.iCacheSize) |
|
487 pos = 0; |
|
488 } |
|
489 timer.Close(); |
|
490 |
|
491 test(fileCacheStats.iLockedSegmentCount > 0); |
|
492 |
|
493 if (gDriveCacheFlags & (EFileCacheWriteEnabled | EFileCacheWriteOn)) |
|
494 TestDirtyDataWrittenToDisk(fileCacheStats); |
|
495 f.Close(); |
|
496 #endif |
|
497 |
|
498 |
|
499 //************************************************************** |
|
500 // Test dirty data written to disk |
|
501 //************************************************************** |
|
502 enum {ETestDataWrittenAfterTimeout, ETestDataWrittenAfterFileClose, ETestDataWrittenAfterSessionClose, ETestEnd}; |
|
503 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
504 for (testNum = 0; testNum < ETestEnd; testNum++) |
|
505 #else |
|
506 for (testNum = 0; testNum < 1; testNum++) |
|
507 #endif |
|
508 { |
|
509 switch(testNum) |
|
510 { |
|
511 case ETestDataWrittenAfterTimeout : test.Next(_L("ETestDataWrittenAfterTimeout")); break; |
|
512 case ETestDataWrittenAfterFileClose : test.Next(_L("ETestDataWrittenAfterFileClose")); break; |
|
513 case ETestDataWrittenAfterSessionClose : test.Next(_L("ETestDataWrittenAfterSessionClose")); break; |
|
514 }; |
|
515 |
|
516 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
517 // flush closed files queue to empty cache |
|
518 test.Printf(_L("Flushing close queue to empty cache...\n")); |
|
519 r = TheFs.ControlIo(gDrive, KControlIoFlushClosedFiles); |
|
520 test_KErrNone(r); |
|
521 #endif |
|
522 |
|
523 r = f.Replace(TheFs, testFile, EFileReadBuffered | EFileWrite | EFileWriteBuffered); |
|
524 test_KErrNone(r); |
|
525 |
|
526 |
|
527 gBufPtr.SetLength(KBufSize); |
|
528 |
|
529 test.Printf(_L("writing file in small blocks to test write caching...\n")); |
|
530 |
|
531 FillBuffer(gBufPtr, KBufSize); |
|
532 TestBuffer(gBufPtr, 0,KBufSize); |
|
533 |
|
534 pos = 0; |
|
535 TInt bufLen = 7; |
|
536 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
537 TInt maxLockedSegmentCount = 0; |
|
538 TInt maxUsedCount = 0; |
|
539 #endif |
|
540 while (pos < KBufSize) |
|
541 { |
|
542 bufLen = (bufLen + 1023) & 0x3FFF; |
|
543 len = Min(bufLen, KBufSize - pos); |
|
544 //RDebug::Print(_L("write len %d"), len); |
|
545 TPtrC8 writePtr = gBuf->Mid(pos, len); |
|
546 r = f.Write(pos, writePtr, len); |
|
547 test_KErrNone(r); |
|
548 pos+= len; |
|
549 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
550 // PrintFileCacheStats(fileCacheStats); |
|
551 TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
552 test_KErrNone(r); |
|
553 maxLockedSegmentCount = Max(maxLockedSegmentCount, fileCacheStats.iLockedSegmentCount); |
|
554 maxUsedCount = Max(maxUsedCount, fileCacheStats.iUsedCount); |
|
555 #endif |
|
556 } |
|
557 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
558 test.Next(_L("Test maxiimum locked page and cacheline count is reasonable")); |
|
559 test.Printf(_L("maxLockedSegmentCount %d maxUsedCount %d"), maxLockedSegmentCount, maxUsedCount); |
|
560 test (maxLockedSegmentCount > 0 && maxLockedSegmentCount <= (gFileCacheConfig.iCacheSize * 2) / KSegmentSize ); |
|
561 test (maxUsedCount > 0 && maxUsedCount <= 5); |
|
562 #endif |
|
563 |
|
564 |
|
565 |
|
566 if (testNum == ETestDataWrittenAfterTimeout) |
|
567 { |
|
568 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
569 if (gDriveCacheFlags & (EFileCacheWriteEnabled | EFileCacheWriteOn)) |
|
570 TestDirtyDataWrittenToDisk(fileCacheStats); |
|
571 #endif |
|
572 f.Close(); |
|
573 } |
|
574 |
|
575 if (testNum == ETestDataWrittenAfterFileClose) |
|
576 { |
|
577 f.Close(); |
|
578 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
579 test.Next(_L("test dirty data has been written to disk after file close")); |
|
580 PrintFileCacheStats(fileCacheStats); |
|
581 test(fileCacheStats.iLockedSegmentCount == 0); |
|
582 #endif |
|
583 } |
|
584 |
|
585 if (testNum == ETestDataWrittenAfterSessionClose) |
|
586 { |
|
587 // verify that closing the file server session (i.e. not the file) |
|
588 // flushes the data to disk... |
|
589 // *** NB This is likely to complete sometime AFTER returning from RFs::Close() |
|
590 // *** as the file server doesn't wait for the disconnect thread to complete !!! |
|
591 |
|
592 TheFs.Close(); |
|
593 TheFs.Connect(); |
|
594 SetSessionPath(gDrive); |
|
595 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
596 test.Next(_L("Test dirty data is eventually written to disk after session close")); |
|
597 TestDirtyDataWrittenToDisk(fileCacheStats); |
|
598 test(fileCacheStats.iLockedSegmentCount == 0); |
|
599 #endif |
|
600 } |
|
601 |
|
602 } // for (TInt testNum = 0; testNum < ETestEnd; testNum++) |
|
603 |
|
604 |
|
605 //#if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
606 // PrintFileCacheStats(fileCacheStats); |
|
607 //#endif |
|
608 |
|
609 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
610 // flush closed files queue to empty cache |
|
611 test.Printf(_L("Flushing close queue to empty cache...\n")); |
|
612 r = TheFs.ControlIo(gDrive, KControlIoFlushClosedFiles); |
|
613 test_KErrNone(r); |
|
614 #endif |
|
615 |
|
616 r = f.Open(TheFs, testFile, EFileRead | EFileReadBuffered | EFileWrite); |
|
617 test_KErrNone(r); |
|
618 |
|
619 TInt size; |
|
620 r = f.Size(size); |
|
621 test (r == KErrNone); |
|
622 test (size = KBufSize); |
|
623 |
|
624 readPtr.Set(gBuf->Des()); |
|
625 |
|
626 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
627 // Allocate full cachelines - so we can enable hole testing |
|
628 TBool allocateAllSegmentsInCacheLine = ETrue; |
|
629 r = controlIo(TheFs, gDrive, KControlIoAllocateMaxSegments, allocateAllSegmentsInCacheLine); |
|
630 test (r == KErrNone); |
|
631 PrintFileCacheStats(fileCacheStats, EFalse); |
|
632 TInt holesDetected = fileCacheStats.iHoleCount; |
|
633 TInt lockFailures = fileCacheStats.iCommitFailureCount + fileCacheStats.iLockFailureCount; |
|
634 #endif |
|
635 |
|
636 test.Next(_L("Test reading a partially filled cacheline")); |
|
637 // create a cacheline with only the first segment filled |
|
638 TInt startPos = KSegmentSize; |
|
639 pos = startPos; |
|
640 len = KSegmentSize; |
|
641 writePtr.Set(gBuf->Mid(pos, len)); |
|
642 r = f.Write(pos, writePtr, len); |
|
643 test_KErrNone(r); |
|
644 |
|
645 // read from first & second segments |
|
646 pos = startPos; |
|
647 len = 8192; |
|
648 RDebug::Print(_L("+%x, %x\n"), pos, len); |
|
649 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
650 readPtr.SetLength(len); |
|
651 r = f.Read(pos, readPtr, len); |
|
652 test_KErrNone(r); |
|
653 TestBuffer(gBufPtr, pos, len); |
|
654 |
|
655 |
|
656 test.Next(_L("Test reading an empty segment towards the end of a partially filled cacheline (hole test)")); |
|
657 // read from segment #4 and beyond end of cacheline into next |
|
658 pos = startPos + KSegmentSize * 4; |
|
659 len = KSegmentSize * 33; // 132 K |
|
660 RDebug::Print(_L("+%x, %x\n"), pos, len); |
|
661 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
662 readPtr.SetLength(len); |
|
663 r = f.Read(pos, readPtr, len); |
|
664 test_KErrNone(r); |
|
665 TestBuffer(gBufPtr, pos, len); |
|
666 |
|
667 |
|
668 test.Next(_L("Test writing to an empty segment towards the end of a partially filled cacheline (hole test)")); |
|
669 // create a cacheline with only the first segment filled |
|
670 startPos = 256 * 1024; |
|
671 pos = startPos; |
|
672 len = KSegmentSize; |
|
673 writePtr.Set(gBuf->Mid(pos, len)); |
|
674 r = f.Write(pos, writePtr, len); |
|
675 test_KErrNone(r); |
|
676 |
|
677 |
|
678 // write into segment 3, 4 & 5 |
|
679 pos = startPos + KSegmentSize * 2; |
|
680 len = KSegmentSize * 3; |
|
681 writePtr.Set(gBuf->Mid(pos, len)); |
|
682 r = f.Write(pos, writePtr, len); |
|
683 test_KErrNone(r); |
|
684 // read back whole cacheline & verify |
|
685 pos = startPos; |
|
686 len = KSegmentSize * 32; // 128 K |
|
687 RDebug::Print(_L("+%x, %x\n"), pos, len); |
|
688 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
689 readPtr.SetLength(len); |
|
690 r = f.Read(pos, readPtr, len); |
|
691 test_KErrNone(r); |
|
692 TestBuffer(gBufPtr, pos, len); |
|
693 |
|
694 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
695 PrintFileCacheStats(fileCacheStats); |
|
696 if (fileCacheStats.iCommitFailureCount + fileCacheStats.iLockFailureCount != lockFailures) |
|
697 { |
|
698 if (gRomPaged) |
|
699 { |
|
700 test.Printf(_L("Lock failures detected on paged ROM, abandoning hole test")); |
|
701 } |
|
702 else |
|
703 { |
|
704 test.Printf(_L("Unexpected lock failures detected on unpaged ROM!!!")); |
|
705 test(0); |
|
706 } |
|
707 } |
|
708 else |
|
709 { |
|
710 test(fileCacheStats.iHoleCount > holesDetected); |
|
711 } |
|
712 // Don't allocate full cachelines any more |
|
713 allocateAllSegmentsInCacheLine = EFalse; |
|
714 r = controlIo(TheFs, gDrive, KControlIoAllocateMaxSegments, allocateAllSegmentsInCacheLine); |
|
715 test (r == KErrNone); |
|
716 #endif |
|
717 |
|
718 |
|
719 |
|
720 gBufPtr.FillZ(); |
|
721 gBufPtr.SetLength(KBufSize); |
|
722 |
|
723 |
|
724 |
|
725 readPtr.SetLength(0); |
|
726 |
|
727 |
|
728 // read from middle of fifth sector to half way thru seventh |
|
729 test.Next(_L("Test read that spans two pages")); |
|
730 pos = 512*4 + 16; |
|
731 len = 512*2; |
|
732 RDebug::Print(_L("+%x, %x\n"), pos, len); |
|
733 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
734 readPtr.SetLength(len); |
|
735 r = f.Read(pos, readPtr, len); |
|
736 test_KErrNone(r); |
|
737 TestBuffer(gBufPtr, pos, len); |
|
738 |
|
739 |
|
740 |
|
741 // read to end of file |
|
742 test.Next(_L("Test reading past end of file")); |
|
743 pos = KBufSize - 0x100; // 0xfb05; |
|
744 len = KBufSize - pos; |
|
745 // pos = KBufSize - 16; |
|
746 // len = 512;; |
|
747 // len = Min(len, KBufSize-pos); |
|
748 RDebug::Print(_L("+%x, %x\n"), pos, len); |
|
749 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
750 readPtr.SetLength(len); |
|
751 r = f.Read(pos, readPtr, len/* + 0x67*/); |
|
752 test_KErrNone(r); |
|
753 |
|
754 test.Next(_L("Test async reads")); |
|
755 // issue 2 async reads |
|
756 pos = KSegmentSize*7 + 16; |
|
757 len = KSegmentSize; |
|
758 RDebug::Print(_L("+%x, %x\n"), pos, len); |
|
759 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
760 readPtr.SetLength(len); |
|
761 |
|
762 TInt pos2 = pos + len; |
|
763 TInt len2 = KSegmentSize; |
|
764 TPtr8 readPtr2 = gBuf->Des(); |
|
765 readPtr2.Set(gBufPtr.MidTPtr(pos2, len2)); |
|
766 readPtr2.SetLength(len2); |
|
767 |
|
768 TRequestStatus status1(KRequestPending); |
|
769 TRequestStatus status2(KRequestPending); |
|
770 |
|
771 f.Read(pos, readPtr, len, status1); |
|
772 f.Read(readPtr2, len2, status2); |
|
773 |
|
774 |
|
775 User::WaitForRequest(status1); |
|
776 User::WaitForRequest(status2); |
|
777 test.Printf(_L("status1 %d status2 %d\n"), status1.Int(), status2.Int()); |
|
778 TestBuffer(gBufPtr, pos, len); |
|
779 TestBuffer(gBufPtr, pos2, len2); |
|
780 |
|
781 |
|
782 test.Next(_L("Read entire file")); |
|
783 |
|
784 for (pos = 0, len = 1; len <= 1024 && pos < KBufSize; len = (len+1) & 0x3FF) |
|
785 { |
|
786 len = Min(len, KBufSize-pos); |
|
787 // RDebug::Print(_L("+%x, %x\n"), pos, len); |
|
788 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
789 readPtr.SetLength(len); |
|
790 |
|
791 r = f.Read(pos, readPtr, len); |
|
792 test_KErrNone(r); |
|
793 TestBuffer(gBufPtr, pos, len); |
|
794 test_KErrNone(r); |
|
795 pos+= len; |
|
796 } |
|
797 |
|
798 TestBuffer(gBufPtr, 0, KBufSize); |
|
799 |
|
800 // read from position zero to ensure it's cached |
|
801 pos = 0; |
|
802 len = 512; |
|
803 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
804 readPtr.SetLength(len); |
|
805 r = f.Read(pos, readPtr, len); |
|
806 test_KErrNone(r); |
|
807 TestBuffer(gBufPtr, pos, len); |
|
808 test_KErrNone(r); |
|
809 |
|
810 f.Close(); |
|
811 |
|
812 |
|
813 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
814 r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
815 test (r == KErrNone); |
|
816 test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue); |
|
817 test(fileCacheStats.iFilesOnClosedQueue == 1); |
|
818 #endif |
|
819 // |
|
820 |
|
821 |
|
822 //************************************************************** |
|
823 // Test closed file queue |
|
824 //************************************************************** |
|
825 enum |
|
826 { |
|
827 ETestCloseQueueEmptyAfterTimeout, |
|
828 ETestCloseQueueEmptyAfterOpenWithDirectIo, |
|
829 ETestCloseQueueEmptyAfterDelete, |
|
830 ETestCloseEnd}; |
|
831 for (testNum = 0; testNum < ETestCloseEnd; testNum++) |
|
832 { |
|
833 |
|
834 test.Next(_L("Reopen file & verify closed queue is empty")); |
|
835 |
|
836 r = f.Open(TheFs, testFile, EFileRead | EFileReadBuffered); |
|
837 test_KErrNone(r); |
|
838 pos = 0; |
|
839 len = 512; |
|
840 readPtr.Set(gBufPtr.MidTPtr(pos, len)); |
|
841 readPtr.SetLength(len); |
|
842 r = f.Read(pos, readPtr, len); |
|
843 test_KErrNone(r); |
|
844 TestBuffer(gBufPtr, pos, len); |
|
845 test_KErrNone(r); |
|
846 |
|
847 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
848 r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
849 test (r == KErrNone); |
|
850 test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue); |
|
851 test(fileCacheStats.iFilesOnClosedQueue == 0); |
|
852 #endif |
|
853 f.Close(); |
|
854 |
|
855 test.Next(_L("close & verify file is back on close queue")); |
|
856 |
|
857 |
|
858 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
859 r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
860 test (r == KErrNone); |
|
861 test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue); |
|
862 test(fileCacheStats.iFilesOnClosedQueue == 1); |
|
863 #endif |
|
864 |
|
865 if (testNum == ETestCloseQueueEmptyAfterDelete) |
|
866 { |
|
867 test.Next(_L("delete file and verify closed queue is empty")); |
|
868 r = TheFs.Delete(testFile); |
|
869 test_KErrNone(r); |
|
870 } |
|
871 if (testNum == ETestCloseQueueEmptyAfterTimeout) |
|
872 { |
|
873 test.Next(_L("wait for a while and verify closed queue is empty")); |
|
874 // wait for closed file queue to empty |
|
875 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
876 User::After(gFileCacheConfig.iClosedFileKeepAliveTime + 1000000); |
|
877 #endif |
|
878 } |
|
879 if (testNum == ETestCloseQueueEmptyAfterOpenWithDirectIo) |
|
880 { |
|
881 test.Next(_L("Re-open file in directIo mode and then close and verify closed queue is empty")); |
|
882 r = f.Open(TheFs, testFile, EFileRead | EFileReadDirectIO); |
|
883 test_KErrNone(r); |
|
884 f.Close(); |
|
885 } |
|
886 |
|
887 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
888 r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
889 test (r == KErrNone); |
|
890 test.Printf(_L("Number of files on closed queue=%d\n"),fileCacheStats.iFilesOnClosedQueue); |
|
891 test(fileCacheStats.iFilesOnClosedQueue == 0); |
|
892 #endif |
|
893 } |
|
894 |
|
895 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
896 // turn lock failure mode back ON (if enabled) |
|
897 simulatelockFailureMode = ETrue; |
|
898 r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); |
|
899 test (r == KErrNone); |
|
900 #endif |
|
901 |
|
902 //************************************************************** |
|
903 // Test opening a file with a silly open mode flags combinations |
|
904 //************************************************************** |
|
905 test.Next(_L("Open file with illegal cache on/off bits")); |
|
906 r = f.Open(TheFs, testFile, EFileRead | EFileReadBuffered | EFileReadDirectIO); |
|
907 test_Value(r, r==KErrArgument); |
|
908 r = f.Open(TheFs, testFile, EFileRead | EFileWriteBuffered | EFileWriteDirectIO); |
|
909 test_Value(r, r==KErrArgument); |
|
910 //********************************** |
|
911 // Test that continuously appending to a file yields the correct size... |
|
912 // NB: Must have lock failure more ON in debug mode for this test to pass |
|
913 //********************************** |
|
914 test.Next(_L("Test appending to a file & checking the file size...")); |
|
915 gBufPtr.SetLength(KBufSize); |
|
916 |
|
917 r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteBuffered); |
|
918 test_KErrNone(r); |
|
919 |
|
920 const TInt KWriteLen = KSegmentSize+1; |
|
921 writePtr.Set(gBuf->Des().Ptr(), KWriteLen); |
|
922 |
|
923 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
924 r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
925 test (r == KErrNone); |
|
926 test.Printf(_L("Number of Write-throughs with dirty data=%d\n"),fileCacheStats.iWriteThroughWithDirtyDataCount); |
|
927 TInt writeThroughWithDirtyDataCountOld = fileCacheStats.iWriteThroughWithDirtyDataCount; |
|
928 TInt writeThroughWithDirtyDataCountNew = writeThroughWithDirtyDataCountOld; |
|
929 #endif |
|
930 |
|
931 TInt fileSize = 0; |
|
932 for (TInt i=0; i<4; i++) |
|
933 { |
|
934 fileSize = 0; |
|
935 r = f.SetSize(fileSize); |
|
936 test (r == KErrNone); |
|
937 for (pos = 0; pos < KMaxFileSize; ) |
|
938 { |
|
939 r = f.Write(pos, writePtr); |
|
940 if (r != KErrNone) |
|
941 { |
|
942 test.Printf(_L("Iter #%d, write pos %d size %d, Write() returned %d"), i, pos, fileSize, r); |
|
943 r = f.Flush(); |
|
944 test.Printf(_L("Flush returned %d"), r); |
|
945 test(0); |
|
946 } |
|
947 test(r == KErrNone); |
|
948 pos+= writePtr.Length(); |
|
949 |
|
950 r = f.Size(fileSize); |
|
951 test (r == KErrNone); |
|
952 if (fileSize != pos) |
|
953 { |
|
954 test.Printf(_L("Iter #%d, write pos %d != size %d"), i, pos, fileSize); |
|
955 r = f.Flush(); |
|
956 test.Printf(_L("Flush returned %d"), r); |
|
957 test(0); |
|
958 } |
|
959 test (fileSize == pos); |
|
960 |
|
961 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
962 r = controlIo(TheFs, gDrive, KControlIoFileCacheStats, fileCacheStats); |
|
963 test (r == KErrNone); |
|
964 writeThroughWithDirtyDataCountNew = fileCacheStats.iWriteThroughWithDirtyDataCount; |
|
965 if (writeThroughWithDirtyDataCountNew > writeThroughWithDirtyDataCountOld) |
|
966 { |
|
967 test.Printf(_L("Iter #%d, write pos %d size %d"), i, pos, fileSize); |
|
968 test.Printf(_L("Number of Write-throughs with dirty data=%d\n"),fileCacheStats.iWriteThroughWithDirtyDataCount); |
|
969 i = 4; |
|
970 break; |
|
971 } |
|
972 #endif |
|
973 |
|
974 } |
|
975 } |
|
976 |
|
977 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
978 test(writeThroughWithDirtyDataCountNew > writeThroughWithDirtyDataCountOld); |
|
979 #endif |
|
980 |
|
981 |
|
982 f.Close(); |
|
983 |
|
984 |
|
985 //TheFs.SetDebugRegister(0); |
|
986 test.End(); |
|
987 } |
|
988 |
|
989 |
|
990 // This thread is used to test what happens if requests are sent to the file server |
|
991 // while the drive thread is hung in the critical notifier server. The requests should |
|
992 // complete immediately with KErrNotReady |
|
993 TInt ReaderThread(TAny* aFileName) |
|
994 { |
|
995 RTest test(_L("T_FILECACHE, ReaderThread")); |
|
996 |
|
997 TDesC& fileName = *(TDesC*) aFileName; |
|
998 |
|
999 RFs fs; |
|
1000 TInt r = fs.Connect(); |
|
1001 test (r==KErrNone); |
|
1002 r = fs.SetSessionPath(gSessionPath); |
|
1003 test (r==KErrNone); |
|
1004 |
|
1005 |
|
1006 RFile file; |
|
1007 r = file.Open(fs, fileName, EFileRead | EFileReadBuffered | EFileShareReadersOrWriters); |
|
1008 test_KErrNone(r); |
|
1009 |
|
1010 RTimer timer; |
|
1011 timer.CreateLocal(); |
|
1012 TRequestStatus reqStat; |
|
1013 timer.After(reqStat,10000000); // Read for 10 secs |
|
1014 |
|
1015 TInt pos=0; |
|
1016 TInt KReadLen = 32768; |
|
1017 TInt retCode = KErrNone; |
|
1018 |
|
1019 for (TInt i=0; reqStat == KRequestPending; i++) |
|
1020 { |
|
1021 r = file.Read(pos, DataBuf, KReadLen); |
|
1022 test_Value(r, r == KErrNone || r == KErrNotReady); |
|
1023 |
|
1024 //test.Printf(_L("ReaderThread: iter %d, read at %d ret %d\n"), i, pos, r); |
|
1025 if (r == KErrNotReady) |
|
1026 retCode = r; |
|
1027 else if (r == KErrNone) |
|
1028 pos = DataBuf.Length() == 0 ? 0: pos + DataBuf.Length(); |
|
1029 if (retCode == KErrNotReady) |
|
1030 test.Printf(_L("ReaderThread: iter %d, read at %d ret %d \n"), i, pos, r); |
|
1031 } |
|
1032 |
|
1033 timer.Close(); |
|
1034 file.Close(); |
|
1035 fs.Close(); |
|
1036 |
|
1037 return retCode; |
|
1038 } |
|
1039 |
|
1040 |
|
1041 void ManualTests() |
|
1042 { |
|
1043 RFile f; |
|
1044 TInt r; |
|
1045 gBufPtr.SetLength(KBufSize); |
|
1046 FillBuffer(gBufPtr, KBufSize); |
|
1047 TestBuffer(gBufPtr, 0,KBufSize); |
|
1048 |
|
1049 TPtrC8 writePtr; |
|
1050 writePtr.Set(gBuf->Des()); |
|
1051 |
|
1052 TFileName testFile = _L("TEST.BIN"); |
|
1053 |
|
1054 #if defined(_DEBUG) |
|
1055 test.Next(_L("Testing writing and then closing with an immediate simulated card eject")); |
|
1056 test.Printf(_L("**********************************************************\n")); |
|
1057 test.Printf(_L("When critical notifier message appears, PRESS RETRY\n")); |
|
1058 test.Printf(_L("**********************************************************\n")); |
|
1059 |
|
1060 r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteBuffered | EFileShareReadersOrWriters); |
|
1061 test_KErrNone(r); |
|
1062 |
|
1063 test.Printf(_L("Writing....")); |
|
1064 r = f.Write(0, writePtr); |
|
1065 test.Printf(_L("Write returned %d\n"), r); |
|
1066 test_KErrNone(r); |
|
1067 |
|
1068 r=TheFs.ControlIo(gDrive, KControlIoSimulateFileCacheWriteFailure); |
|
1069 test_KErrNone(r); |
|
1070 |
|
1071 f.Close(); |
|
1072 |
|
1073 TEntry entry; |
|
1074 |
|
1075 // wait for re-insertion.... |
|
1076 do |
|
1077 { |
|
1078 r = TheFs.Entry(testFile, entry); |
|
1079 User::After(500000); |
|
1080 } |
|
1081 while (r == KErrNotReady); |
|
1082 test_KErrNone(r); |
|
1083 |
|
1084 test.Printf(_L("FileSize %d expected %d\n"), entry.iSize, writePtr.Length()); |
|
1085 |
|
1086 // test all data is written to disk |
|
1087 test (entry.iSize == writePtr.Length()); |
|
1088 #endif |
|
1089 |
|
1090 |
|
1091 test.Next(_L("Testing writing and then ejecting card")); |
|
1092 |
|
1093 // r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteDirectIO); |
|
1094 r = f.Replace(TheFs, testFile, EFileWrite | EFileWriteBuffered | EFileShareReadersOrWriters); |
|
1095 test_KErrNone(r); |
|
1096 writePtr.Set(gBuf->Des()); |
|
1097 |
|
1098 |
|
1099 // set the file size first so that the cluster chain already exists |
|
1100 r = f.SetSize(writePtr.Length()); |
|
1101 test.Printf(_L("SetSize returned %d")); |
|
1102 |
|
1103 // Create another thread which will attempt to issue reads while this thread is suspended |
|
1104 // These reads should complete with KErrNotReady |
|
1105 const TInt KHeapSize = 32768; |
|
1106 test.Printf(_L("Creating file-reading thread\n")); |
|
1107 RThread readerThread; |
|
1108 readerThread.Create(_L("FileReaderThread"), ReaderThread, KDefaultStackSize, KHeapSize, KHeapSize, &testFile); |
|
1109 |
|
1110 test.Printf(_L("Writing....")); |
|
1111 r = f.Write(0, writePtr); |
|
1112 test.Printf(_L("Write returned %d\n"), r); |
|
1113 |
|
1114 |
|
1115 test.Printf(_L("Waiting 5 seconds.\n")); |
|
1116 test.Printf(_L("**********************************************************\n")); |
|
1117 test.Printf(_L("Please press a key, EJECT MEDIA BEFORE WRITE TIMER EXPIRES,\n")); |
|
1118 test.Printf(_L("wait for critical notifier, replace media and retry\n")); |
|
1119 test.Printf(_L("**********************************************************\n")); |
|
1120 // test.Printf(_L("press any key...")); |
|
1121 test.Getch(); |
|
1122 test.Printf(_L("\n")); |
|
1123 |
|
1124 test.Printf(_L("Writing....")); |
|
1125 r = f.Write(0, writePtr); |
|
1126 test.Printf(_L("Write returned %d\n"), r); |
|
1127 readerThread.Resume(); |
|
1128 |
|
1129 User::After(5000000); |
|
1130 |
|
1131 do |
|
1132 { |
|
1133 test.Printf(_L("Flushing....\n")); |
|
1134 r = f.Flush(); |
|
1135 test.Printf(_L("Flush returned %d\n"), r); |
|
1136 if (r != KErrNone) |
|
1137 User::After(5000000); |
|
1138 } |
|
1139 while (r != KErrNone); |
|
1140 |
|
1141 |
|
1142 // r = f.Write(0, writePtr); |
|
1143 // test.Printf(_L("Write returned %d")); |
|
1144 |
|
1145 // test_KErrNone(r); |
|
1146 |
|
1147 test.Next(_L("Testing reader thread completed with KErrNotReady")); |
|
1148 TRequestStatus status; |
|
1149 readerThread.Logon(status); |
|
1150 readerThread.Resume(); |
|
1151 User::WaitForRequest(status); |
|
1152 test.Printf(_L("ReaderThread status %d\n"), status.Int()); |
|
1153 test (status.Int() == KErrNotReady); |
|
1154 readerThread.Close(); |
|
1155 |
|
1156 test.Printf(_L("press any key...")); |
|
1157 test.Getch(); |
|
1158 test.Printf(_L("\n")); |
|
1159 |
|
1160 f.Close(); |
|
1161 } |
|
1162 |
|
1163 |
|
1164 LOCAL_C void DoTestFileRead(TUint aFileMode, TInt aReadBlockSize) |
|
1165 // |
|
1166 // Do Read Test |
|
1167 // |
|
1168 { |
|
1169 |
|
1170 RFile file; |
|
1171 TInt r=file.Open(TheFs,_L("READTEST.XXX"),EFileStream | aFileMode); |
|
1172 test_KErrNone(r); |
|
1173 |
|
1174 TInt maxReadCount=KMaxFileSize/aReadBlockSize; |
|
1175 TInt loopCount=0; |
|
1176 |
|
1177 TTime startTime; |
|
1178 TTime endTime; |
|
1179 |
|
1180 RTimer timer; |
|
1181 timer.CreateLocal(); |
|
1182 TRequestStatus reqStat; |
|
1183 timer.After(reqStat,10000000); // After 10 secs |
|
1184 startTime.HomeTime(); |
|
1185 |
|
1186 FOREVER |
|
1187 { |
|
1188 TInt pos=0; |
|
1189 file.Seek(ESeekStart,pos); |
|
1190 for(TInt ii=0;ii<maxReadCount;ii++) |
|
1191 { |
|
1192 r = file.Read(DataBuf,aReadBlockSize); |
|
1193 test_KErrNone(r); |
|
1194 #if defined(_DEBUG) |
|
1195 for(TInt jj=0;jj<DataBuf.Size();jj++) |
|
1196 { |
|
1197 if (DataBuf[jj] != ((jj+ii*aReadBlockSize)%256)) |
|
1198 { |
|
1199 test.Printf(_L("len %d size %d jj %d ii %d"), DataBuf.Length(), DataBuf.Size(), jj, ii); |
|
1200 test(0); |
|
1201 } |
|
1202 // test(DataBuf[jj] == ((jj+ii*aReadBlockSize)%256) ); |
|
1203 } |
|
1204 #endif |
|
1205 if (reqStat!=KRequestPending) |
|
1206 { |
|
1207 endTime.HomeTime(); |
|
1208 |
|
1209 TInt functionCalls=loopCount*maxReadCount+ii; |
|
1210 // TReal rate = ( TReal32(functionCalls) * TReal32(aReadBlockSize) ) / 10; |
|
1211 // test.Printf(_L("Read %5d byte blocks:\t%11.3f KBytes/s\n"), aReadBlockSize, rate / (KOneK)); |
|
1212 |
|
1213 TReal transferRate = |
|
1214 (TReal32(functionCalls) * TReal32(aReadBlockSize)) / |
|
1215 TReal(endTime.MicroSecondsFrom(startTime).Int64()) * TReal(KOneMeg) / TReal(KOneK); |
|
1216 test.Printf(_L("Read %5d byte blocks:\t%11.3f KBytes/s\n"), aReadBlockSize,transferRate); |
|
1217 |
|
1218 timer.Close(); |
|
1219 file.Close(); |
|
1220 |
|
1221 return; |
|
1222 } |
|
1223 } |
|
1224 loopCount++; |
|
1225 } |
|
1226 } |
|
1227 |
|
1228 LOCAL_C void DoTestFileWrite(TUint aFileMode, TInt aWriteBlockSize) |
|
1229 // |
|
1230 // Do Write benchmark |
|
1231 // |
|
1232 { |
|
1233 DataBuf.SetLength(aWriteBlockSize); |
|
1234 TInt maxWriteCount=KMaxFileSize/aWriteBlockSize; |
|
1235 TInt loopCount=0; |
|
1236 |
|
1237 RFile file; |
|
1238 TInt r = file.Replace(TheFs,_L("WRITETST"),EFileStream | aFileMode); |
|
1239 test (r == KErrNone); |
|
1240 |
|
1241 TTime startTime; |
|
1242 TTime endTime; |
|
1243 |
|
1244 RTimer timer; |
|
1245 timer.CreateLocal(); |
|
1246 TRequestStatus reqStat; |
|
1247 timer.After(reqStat,10000000); // After 10 secs |
|
1248 startTime.HomeTime(); |
|
1249 |
|
1250 |
|
1251 |
|
1252 FOREVER |
|
1253 { |
|
1254 TInt pos=0; |
|
1255 file.Seek(ESeekStart,pos); |
|
1256 for(TInt ii=0;ii<maxWriteCount;ii++) |
|
1257 { |
|
1258 r = file.Write(DataBuf); |
|
1259 test_KErrNone(r); |
|
1260 if (reqStat!=KRequestPending) |
|
1261 { |
|
1262 |
|
1263 // TReal rate = (TReal32(functionCalls) * TReal32(aWriteBlockSize)) / 10; |
|
1264 // test.Printf(_L("Write %5d byte blocks:\t%11.3f KBytes/s\n"), aWriteBlockSize, rate / (KOneK)); |
|
1265 |
|
1266 r = file.Flush(); |
|
1267 test_KErrNone(r); |
|
1268 |
|
1269 endTime.HomeTime(); |
|
1270 |
|
1271 TInt functionCalls=loopCount*maxWriteCount+ii; |
|
1272 TReal transferRate = |
|
1273 (TReal32(functionCalls) * TReal32(aWriteBlockSize)) / |
|
1274 TReal(endTime.MicroSecondsFrom(startTime).Int64()) * TReal(KOneMeg) / TReal(KOneK); |
|
1275 test.Printf(_L("Write %5d byte blocks:\t%11.3f KBytes/s\n"), aWriteBlockSize,transferRate); |
|
1276 |
|
1277 file.Close(); |
|
1278 timer.Close(); |
|
1279 TInt r=TheFs.Delete(_L("WRITETST")); |
|
1280 test_KErrNone(r); |
|
1281 return; |
|
1282 } |
|
1283 } |
|
1284 loopCount++; |
|
1285 } |
|
1286 } |
|
1287 |
|
1288 LOCAL_C void TestFileRead(TUint aFileMode) |
|
1289 // |
|
1290 // Benchmark read method |
|
1291 // |
|
1292 { |
|
1293 |
|
1294 // ClearSessionDirectory(); |
|
1295 test.Next(_L("Benchmark read method")); |
|
1296 // test.Printf(_L("aFileMode %08X\n"), aFileMode); |
|
1297 PrintFileMode(aFileMode); |
|
1298 |
|
1299 // Create test data |
|
1300 TBuf8<1024> testdata(1024); |
|
1301 for (TInt i=0;i<testdata.MaxSize();i++) |
|
1302 testdata[i]=TText8(i%256); |
|
1303 |
|
1304 // create & fill the file |
|
1305 RFile file; |
|
1306 TInt r=file.Replace(TheFs,_L("READTEST.XXX"),EFileStream | aFileMode); |
|
1307 test_KErrNone(r); |
|
1308 |
|
1309 test.Printf(_L("Creating test file.....")); |
|
1310 TInt count=KMaxFileSize/testdata.Length(); |
|
1311 while (count--) |
|
1312 file.Write(testdata); |
|
1313 file.Close(); |
|
1314 test.Printf(_L("done.\n")); |
|
1315 |
|
1316 #ifdef SYMBIAN_TEST_EXTENDED_BUFFER_SIZES |
|
1317 |
|
1318 DoTestFileRead(aFileMode, 1); |
|
1319 DoTestFileRead(aFileMode, 2); |
|
1320 DoTestFileRead(aFileMode, 4); |
|
1321 DoTestFileRead(aFileMode, 8); |
|
1322 DoTestFileRead(aFileMode, 16); |
|
1323 DoTestFileRead(aFileMode, 32); |
|
1324 DoTestFileRead(aFileMode, 64); |
|
1325 DoTestFileRead(aFileMode, 128); |
|
1326 DoTestFileRead(aFileMode, 256); |
|
1327 DoTestFileRead(aFileMode, 512); |
|
1328 DoTestFileRead(aFileMode, 1024); |
|
1329 DoTestFileRead(aFileMode, 2048); |
|
1330 DoTestFileRead(aFileMode, 4096); |
|
1331 DoTestFileRead(aFileMode, 8192); |
|
1332 DoTestFileRead(aFileMode, 16384); |
|
1333 DoTestFileRead(aFileMode, 32768); |
|
1334 DoTestFileRead(aFileMode, 65536); |
|
1335 DoTestFileRead(aFileMode, 131072); |
|
1336 #else |
|
1337 //TheFs.SetDebugRegister(KCACHE); |
|
1338 DoTestFileRead(aFileMode, 1); |
|
1339 DoTestFileRead(aFileMode, 16); |
|
1340 DoTestFileRead(aFileMode, 512); |
|
1341 //TheFs.SetDebugRegister(0); |
|
1342 DoTestFileRead(aFileMode, 4 * 1024); |
|
1343 DoTestFileRead(aFileMode, 32 * 1024); |
|
1344 DoTestFileRead(aFileMode, 64 * 1024); |
|
1345 DoTestFileRead(aFileMode, 128 * 1024); |
|
1346 DoTestFileRead(aFileMode, 256 * 1024); |
|
1347 #endif |
|
1348 |
|
1349 r=TheFs.Delete(_L("READTEST.XXX")); |
|
1350 |
|
1351 |
|
1352 |
|
1353 test_KErrNone(r); |
|
1354 } |
|
1355 |
|
1356 |
|
1357 LOCAL_C void TestFileWrite(TUint aFileMode) |
|
1358 // |
|
1359 // Benchmark write method |
|
1360 // |
|
1361 { |
|
1362 // ClearSessionDirectory(); |
|
1363 test.Next(_L("Benchmark write method")); |
|
1364 // test.Printf(_L("aFileMode %08X\n"), aFileMode); |
|
1365 PrintFileMode(aFileMode); |
|
1366 |
|
1367 |
|
1368 // RFile file; |
|
1369 // TInt r = file.Replace(TheFs,_L("WRITETST"),EFileStream | aFileMode); |
|
1370 // test_KErrNone(r); |
|
1371 |
|
1372 |
|
1373 #ifdef SYMBIAN_TEST_EXTENDED_BUFFER_SIZES |
|
1374 DoTestFileWrite(aFileMode, 1); |
|
1375 DoTestFileWrite(aFileMode, 2); |
|
1376 DoTestFileWrite(aFileMode, 4); |
|
1377 DoTestFileWrite(aFileMode, 8); |
|
1378 DoTestFileWrite(aFileMode, 16); |
|
1379 DoTestFileWrite(aFileMode, 32); |
|
1380 DoTestFileWrite(aFileMode, 64); |
|
1381 DoTestFileWrite(aFileMode, 128); |
|
1382 DoTestFileWrite(aFileMode, 256); |
|
1383 DoTestFileWrite(aFileMode, 512); |
|
1384 DoTestFileWrite(aFileMode, 1024); |
|
1385 DoTestFileWrite(aFileMode, 2048); |
|
1386 DoTestFileWrite(aFileMode, 4096); |
|
1387 DoTestFileWrite(aFileMode, 8192); |
|
1388 DoTestFileWrite(aFileMode, 16384); |
|
1389 DoTestFileWrite(aFileMode, 32768); |
|
1390 DoTestFileWrite(aFileMode, 65536); |
|
1391 DoTestFileWrite(aFileMode, 131072); |
|
1392 #else |
|
1393 DoTestFileWrite(aFileMode, 1); |
|
1394 DoTestFileWrite(aFileMode, 16); |
|
1395 DoTestFileWrite(aFileMode, 512); |
|
1396 DoTestFileWrite(aFileMode, 4 * 1024); |
|
1397 DoTestFileWrite(aFileMode, 32 * 1024); |
|
1398 DoTestFileWrite(aFileMode, 64 * 1024); |
|
1399 DoTestFileWrite(aFileMode, 128 * 1024); |
|
1400 DoTestFileWrite(aFileMode, 256 * 1024); |
|
1401 #endif |
|
1402 } |
|
1403 |
|
1404 enum CommandId { |
|
1405 CMD_NO_COMMAND, |
|
1406 CMD_HELP, |
|
1407 CMD_DISPLAY_CACHE_FLAGS, |
|
1408 CMD_WRITE_CACHE_FLAGS, |
|
1409 CMD_PERFORMANCE_TEST, |
|
1410 CMD_MANUAL_TEST |
|
1411 }; |
|
1412 |
|
1413 |
|
1414 class CommandLineOption { |
|
1415 public: |
|
1416 CommandLineOption(const TPtrC &s, CommandId i) : str(s), id(i) { } |
|
1417 |
|
1418 const TPtrC str; |
|
1419 CommandId id; |
|
1420 |
|
1421 private: |
|
1422 CommandLineOption() { } |
|
1423 }; |
|
1424 |
|
1425 // Lists of command line options |
|
1426 static const CommandLineOption commandList[] = { |
|
1427 CommandLineOption(_L("-help"), CMD_HELP), |
|
1428 CommandLineOption(_L("-h"), CMD_HELP), |
|
1429 CommandLineOption(_L("-?"), CMD_HELP), |
|
1430 CommandLineOption(_L("/?"), CMD_HELP), |
|
1431 CommandLineOption(_L("-d"), CMD_DISPLAY_CACHE_FLAGS), |
|
1432 CommandLineOption(_L("-w"), CMD_WRITE_CACHE_FLAGS), |
|
1433 CommandLineOption(_L("-p"), CMD_PERFORMANCE_TEST), |
|
1434 CommandLineOption(_L("-m"), CMD_MANUAL_TEST), |
|
1435 }; |
|
1436 |
|
1437 |
|
1438 |
|
1439 LOCAL_C void printHelp() { |
|
1440 test.Printf(_L("Option Explanation\r\n")); |
|
1441 test.Printf(_L("-help Print this text\r\n")); |
|
1442 test.Printf(_L("-d Display cache flags\n")); |
|
1443 test.Printf(_L("-p Performance test\n")); |
|
1444 } |
|
1445 |
|
1446 |
|
1447 |
|
1448 ///////////////////////////////////////////////////////////////////////////// |
|
1449 // Function: |
|
1450 // bool parseCommandLine() |
|
1451 // |
|
1452 // Parameters: |
|
1453 // - |
|
1454 // |
|
1455 // Return value: |
|
1456 // true if command line options was correct, false if any command was |
|
1457 // invalid |
|
1458 // |
|
1459 // Purpose: |
|
1460 // Parses the command line |
|
1461 // |
|
1462 ///////////////////////////////////////////////////////////////////////////// |
|
1463 |
|
1464 //TBuf<512> commandLine; |
|
1465 |
|
1466 |
|
1467 LOCAL_C bool ParseCommandLine( const TDesC& aCommand ) |
|
1468 { |
|
1469 TLex lex(aCommand); |
|
1470 TInt tokenCount = 0; |
|
1471 |
|
1472 gDriveToTest='C'; |
|
1473 gRunTests = ETrue; |
|
1474 |
|
1475 for (TPtrC token=lex.NextToken(); token.Length() != 0;token.Set(lex.NextToken())) |
|
1476 { |
|
1477 tokenCount++; |
|
1478 |
|
1479 // |
|
1480 // Search the list of commands for a match. |
|
1481 // |
|
1482 CommandId commandId = CMD_NO_COMMAND; |
|
1483 for (TUint i = 0; i < sizeof commandList / sizeof commandList[0]; i++) |
|
1484 { |
|
1485 if (token.CompareF(commandList[i].str) == 0) |
|
1486 { |
|
1487 // |
|
1488 // Found a matching string |
|
1489 // |
|
1490 commandId = commandList[i].id; |
|
1491 break; |
|
1492 } |
|
1493 } |
|
1494 |
|
1495 switch (commandId) |
|
1496 { |
|
1497 case CMD_NO_COMMAND: |
|
1498 { |
|
1499 TFileName thisfile=RProcess().FileName(); |
|
1500 if (token.MatchF(thisfile)==0) |
|
1501 { |
|
1502 token.Set(lex.NextToken()); |
|
1503 } |
|
1504 test.Printf(_L("CLP=%S\n"),&token); |
|
1505 |
|
1506 TChar ch = token[0]; |
|
1507 if (ch.IsAlpha()) |
|
1508 { |
|
1509 if(token.Length()!=0) |
|
1510 { |
|
1511 gDriveToTest=token[0]; |
|
1512 gDriveToTest.UpperCase(); |
|
1513 } |
|
1514 else |
|
1515 gDriveToTest='C'; |
|
1516 lex.NextToken(); |
|
1517 } |
|
1518 } |
|
1519 break; |
|
1520 |
|
1521 case CMD_HELP: |
|
1522 printHelp(); |
|
1523 gRunTests = EFalse; |
|
1524 break; |
|
1525 |
|
1526 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
1527 case CMD_WRITE_CACHE_FLAGS: |
|
1528 { |
|
1529 token.Set(lex.NextToken()); |
|
1530 if (token.Length() == 0) { |
|
1531 printHelp(); |
|
1532 return false; |
|
1533 } |
|
1534 // |
|
1535 // Extract flags (in hex) from next token. |
|
1536 // |
|
1537 TPtrC numStr(token); |
|
1538 TUint val; |
|
1539 TInt r = TLex(numStr).Val(val, EHex); |
|
1540 if (r != KErrNone) { |
|
1541 printHelp(); |
|
1542 return false; |
|
1543 } |
|
1544 gDriveCacheFlags = TFileCacheFlags(val); |
|
1545 gWriteCacheFlags = ETrue; |
|
1546 gRunTests = EFalse; |
|
1547 break; |
|
1548 } |
|
1549 |
|
1550 case CMD_DISPLAY_CACHE_FLAGS: |
|
1551 gDisplayCacheFlags = ETrue; |
|
1552 gRunTests = EFalse; |
|
1553 break; |
|
1554 #endif |
|
1555 case CMD_PERFORMANCE_TEST: |
|
1556 gRunPerformanceTests = ETrue; |
|
1557 gRunUnitTests = EFalse; |
|
1558 break; |
|
1559 |
|
1560 case CMD_MANUAL_TEST: |
|
1561 gRunManualTests = ETrue; |
|
1562 gRunUnitTests = EFalse; |
|
1563 break; |
|
1564 |
|
1565 default: |
|
1566 test.Printf(_L("Sorry, command option '%S' not implemented\n"), |
|
1567 &token); |
|
1568 break; |
|
1569 } |
|
1570 |
|
1571 } |
|
1572 return true; |
|
1573 } |
|
1574 |
|
1575 |
|
1576 LOCAL_C TBool parseCommandLine() { |
|
1577 // |
|
1578 // Loop through all tokens in the command line |
|
1579 // |
|
1580 TInt cmdLineLen = User::CommandLineLength(); |
|
1581 HBufC* cmdLineBuf = HBufC::New( cmdLineLen ); |
|
1582 if( !cmdLineBuf ) |
|
1583 { |
|
1584 return false; |
|
1585 } |
|
1586 TPtr ptr = cmdLineBuf->Des(); |
|
1587 User::CommandLine(ptr); |
|
1588 |
|
1589 bool err = ParseCommandLine( *cmdLineBuf ); |
|
1590 delete cmdLineBuf; |
|
1591 return err; |
|
1592 } |
|
1593 |
|
1594 GLDEF_C void CallTestsL() |
|
1595 // |
|
1596 // Do tests relative to the session path |
|
1597 // |
|
1598 { |
|
1599 TestsInit(); |
|
1600 |
|
1601 TVolumeInfo volInfo; |
|
1602 TInt r = TheFs.Volume(volInfo, gDrive); |
|
1603 test (r == KErrNone); |
|
1604 |
|
1605 TFullName extName; |
|
1606 r = TheFs.ExtensionName(extName,gDrive, 0); |
|
1607 if (r == KErrNone) |
|
1608 { |
|
1609 test.Printf(_L("File system extension present (%S)\n"), &extName); |
|
1610 } |
|
1611 |
|
1612 if ((volInfo.iDrive.iType == EMediaRam) || |
|
1613 ((gDriveCacheFlags & (EFileCacheReadEnabled | EFileCacheReadOn)) == 0)) |
|
1614 { |
|
1615 if (gRunPerformanceTests) |
|
1616 { |
|
1617 TestFileRead(EFileReadDirectIO); |
|
1618 TestFileWrite(EFileWriteDirectIO); |
|
1619 } |
|
1620 TestsEnd(); |
|
1621 return; |
|
1622 } |
|
1623 |
|
1624 if (gRunUnitTests) |
|
1625 UnitTests(); |
|
1626 |
|
1627 if (gRunManualTests) |
|
1628 { |
|
1629 ManualTests(); |
|
1630 } |
|
1631 |
|
1632 if (gRunPerformanceTests) |
|
1633 { |
|
1634 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
1635 // turn OFF lock failure mode |
|
1636 TBool simulatelockFailureMode = EFalse; |
|
1637 r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); |
|
1638 test (r == KErrNone); |
|
1639 #endif |
|
1640 |
|
1641 TestFileRead(EFileReadDirectIO); |
|
1642 if (gDriveCacheFlags & (EFileCacheReadEnabled | EFileCacheReadOn)) |
|
1643 { |
|
1644 TestFileRead(EFileReadBuffered | EFileReadAheadOff); |
|
1645 TestFileRead(EFileReadBuffered | EFileReadAheadOn); |
|
1646 } |
|
1647 |
|
1648 TestFileWrite(EFileWriteDirectIO); |
|
1649 |
|
1650 if (gDriveCacheFlags & (EFileCacheWriteEnabled | EFileCacheWriteOn)) |
|
1651 TestFileWrite(EFileWriteBuffered); |
|
1652 |
|
1653 |
|
1654 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
1655 // turn lock failure mode back ON (if enabled) |
|
1656 simulatelockFailureMode = ETrue; |
|
1657 r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode); |
|
1658 test (r == KErrNone); |
|
1659 #endif |
|
1660 } // if (gRunPerformanceTests) |
|
1661 |
|
1662 TestsEnd(); |
|
1663 } |
|
1664 |
|
1665 |
|
1666 |
|
1667 LOCAL_C void DoTests(TInt aDrive) |
|
1668 // |
|
1669 // Do testing on aDrive |
|
1670 // |
|
1671 { |
|
1672 |
|
1673 SetSessionPath(aDrive); |
|
1674 |
|
1675 // !!! Disable platform security tests until we get the new APIs |
|
1676 // if(User::Capability() & KCapabilityRoot) |
|
1677 // CheckMountLFFS(TheFs,driveLetter); |
|
1678 |
|
1679 User::After(1000000); |
|
1680 |
|
1681 TInt r=TheFs.MkDirAll(gSessionPath); |
|
1682 test_Value(r, r == KErrNone || r == KErrAlreadyExists); |
|
1683 TheFs.ResourceCountMarkStart(); |
|
1684 |
|
1685 TRAP(r,CallTestsL()); |
|
1686 test_KErrNone(r); |
|
1687 |
|
1688 TheFs.ResourceCountMarkEnd(); |
|
1689 } |
|
1690 |
|
1691 |
|
1692 void Format(TInt aDrive) |
|
1693 // |
|
1694 // Format current drive |
|
1695 // |
|
1696 { |
|
1697 |
|
1698 test.Next(_L("Format")); |
|
1699 TBuf<4> driveBuf=_L("?:\\"); |
|
1700 driveBuf[0]=(TText)(aDrive+'A'); |
|
1701 RFormat format; |
|
1702 TInt count; |
|
1703 TInt r=format.Open(TheFs,driveBuf,EQuickFormat,count); |
|
1704 //TInt r=format.Open(TheFs,driveBuf,EFullFormat,count); |
|
1705 test.Printf(_L("RFormat::Open() returned %d\n"), r); |
|
1706 test_KErrNone(r); |
|
1707 while(count) |
|
1708 { |
|
1709 TInt r=format.Next(count); |
|
1710 test_KErrNone(r); |
|
1711 } |
|
1712 format.Close(); |
|
1713 } |
|
1714 |
|
1715 GLDEF_C TInt E32Main() |
|
1716 // |
|
1717 // Test with drive nearly full |
|
1718 // |
|
1719 { |
|
1720 |
|
1721 CTrapCleanup* cleanup; |
|
1722 cleanup=CTrapCleanup::New(); |
|
1723 |
|
1724 __UHEAP_MARK; |
|
1725 |
|
1726 TBool parseOk = parseCommandLine(); |
|
1727 if (!parseOk) |
|
1728 User::Leave(KErrNotSupported); |
|
1729 |
|
1730 |
|
1731 TInt r = TheFs.Connect(); |
|
1732 test_KErrNone(r); |
|
1733 |
|
1734 r=TheFs.CharToDrive(gDriveToTest,gDrive); |
|
1735 test_KErrNone(r); |
|
1736 |
|
1737 #if !defined(__WINS__) |
|
1738 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
1739 test.Start(_L("Check that the rom is paged")); |
|
1740 TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress(); |
|
1741 if (romHeader->iPageableRomStart != NULL) |
|
1742 { |
|
1743 test.Printf(_L("ROM is paged\n")); |
|
1744 gRomPaged = ETrue; |
|
1745 } |
|
1746 #endif |
|
1747 #endif |
|
1748 |
|
1749 // Get the TFileCacheFlags for this drive |
|
1750 r = TheFs.Volume(gVolInfo, gDrive); |
|
1751 if (r == KErrNotReady) |
|
1752 { |
|
1753 TDriveInfo info; |
|
1754 TInt err = TheFs.Drive(info,gDrive); |
|
1755 test_KErrNone(err); |
|
1756 if (info.iType == EMediaNotPresent) |
|
1757 test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)gDriveToTest); |
|
1758 else |
|
1759 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); |
|
1760 } |
|
1761 else if (r == KErrCorrupt) |
|
1762 { |
|
1763 test.Printf(_L("%c: Media corruption; previous test may have aborted; else, check hardware\n"), (TUint)gDriveToTest); |
|
1764 } |
|
1765 test_KErrNone(r); |
|
1766 gDriveCacheFlags = gVolInfo.iFileCacheFlags; |
|
1767 test.Printf(_L("DriveCacheFlags for drive %C = %08X\n"), (TInt) gDriveToTest, gDriveCacheFlags); |
|
1768 |
|
1769 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
1770 PrintFileCacheConfig(gFileCacheConfig, gDrive); |
|
1771 |
|
1772 if (gDisplayCacheFlags) |
|
1773 { |
|
1774 test.Printf(_L("Press any key...\n")); |
|
1775 test.Getch(); |
|
1776 } |
|
1777 |
|
1778 if (gWriteCacheFlags) |
|
1779 { |
|
1780 test.Printf(_L("Writing DriveCacheFlags for drive %C = %08X\n"), (TInt) gDriveToTest, gDriveCacheFlags); |
|
1781 r = controlIo(TheFs,gDrive, KControlIoFileCacheFlagsWrite, gDriveCacheFlags); |
|
1782 test (r == KErrNone); |
|
1783 } |
|
1784 #endif |
|
1785 |
|
1786 if (gRunTests) |
|
1787 { |
|
1788 test.Title(); |
|
1789 |
|
1790 |
|
1791 test.Start(_L("Starting tests...")); |
|
1792 |
|
1793 if ((gVolInfo.iDrive.iMediaAtt & KMediaAttFormattable)) |
|
1794 Format(gDrive); |
|
1795 |
|
1796 //TheFs.SetDebugRegister(KCACHE); |
|
1797 DoTests(gDrive); |
|
1798 //TheFs.SetDebugRegister(0); |
|
1799 test.End(); |
|
1800 // } |
|
1801 } |
|
1802 |
|
1803 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
1804 TFileCacheStats fileCacheStats; |
|
1805 PrintFileCacheStats(fileCacheStats); |
|
1806 #endif |
|
1807 |
|
1808 TheFs.Close(); |
|
1809 test.Close(); |
|
1810 __UHEAP_MARKEND; |
|
1811 delete cleanup; |
|
1812 return(KErrNone); |
|
1813 } |