os/kernelhwsrv/kerneltest/f32test/server/t_rcache.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32test\server\t_rcache.cpp
    15 // 
    16 //
    17 
    18 /**
    19  @file
    20  @internalTechnology 
    21 */
    22 #define __E32TEST_EXTENSION__
    23 #include <f32file.h>
    24 #include <e32test.h>
    25 #include <e32svr.h>
    26 #include <e32const.h>
    27 #include <e32const_private.h>
    28 #include <f32dbg.h>
    29 #include "t_server.h"
    30 #include <e32twin.h>
    31 #include <e32rom.h>
    32 #include <hal.h>
    33 #include <u32hal.h>
    34 
    35 const TInt KTotalCacheSize = 32 * 1024 * 1024;
    36 const TInt KDefaultCacheSize = (128 + 12) * 1024;
    37 const TInt KFilesNeededToFillCache = (KTotalCacheSize / KDefaultCacheSize) + 2;
    38 
    39 
    40 //----------------------------------------------------------------------------------------------
    41 //! @SYMTestCaseID      PBASE-T_RCACHE-0190
    42 //! @SYMTestType        CIT
    43 //! @SYMPREQ            PREQ914
    44 //! @SYMTestCaseDesc    This test case is exercising the Read Caching functionality added to
    45 //!						the File Server. There are negative and positive tests.
    46 //! @SYMTestActions     0   setup the environment to execute the tests
    47 //!						1	TestNegative creates situations where the cached content needs to be
    48 //!							flushed or removed  from the cache by corrupting files and verifies
    49 //!							the cache behaviour
    50 //!						2 	TestSimpleRead ensures that the cache is working in the simple cases,
    51 //!							with a combination of sync and async reads:
    52 //!								a. The file fits in the cache
    53 //!								b. The file doesn't fit in the cache
    54 //!						3 	TestRepeatedRead verifies the cache behaviour when a file is read an
    55 //!							arbitrary number of times, with and without other operations ongoing
    56 //!						4	TestReadAhead reads 3 times from a file and verifies that the read
    57 //!							ahead functionality acts afterwards.
    58 //!						5	TestConcurrent reads files concurrently and verifies how the cache
    59 //!							copes with it.
    60 //!						6 	TestFillCache fills the cache and then executes TestSimpleRead.
    61 //!
    62 //! @SYMTestExpectedResults finishes if the read cache behaves as expected, panics otherwise
    63 //! @SYMTestPriority        High
    64 //! @SYMTestStatus          Implemented
    65 //----------------------------------------------------------------------------------------------
    66 
    67 
    68 ////////////////////////////////////////////////////////////
    69 // Template functions encapsulating ControlIo magic
    70 //
    71 GLDEF_D template <class C>
    72 GLDEF_C TInt controlIo(RFs &fs, TInt drv, TInt fkn, C &c)
    73 {
    74     TPtr8 ptrC((TUint8 *)&c, sizeof(C), sizeof(C));
    75 
    76     TInt r = fs.ControlIo(drv, fkn, ptrC);
    77 
    78     return r;
    79 }
    80 
    81 GLDEF_D RTest test(_L("T_RCACHE"));
    82 
    83 GLDEF_D	RFs TheFs;
    84 GLDEF_D TInt gDrive;
    85 GLDEF_D TFileName gSessionPath;
    86 GLDEF_D TChar gDriveToTest;
    87 TThreadId gMainThreadId;
    88 
    89 LOCAL_D HBufC8* gBuf = NULL;
    90 LOCAL_D TPtr8 gBufReadPtr(NULL, 0);
    91 LOCAL_D HBufC8* gBufSec = NULL;
    92 LOCAL_D TPtr8 gBufWritePtr(NULL, 0);
    93 
    94 LOCAL_D const TInt KOneK = 1024;
    95 LOCAL_D const TInt KOneMeg = KOneK * 1024;
    96 LOCAL_D const TInt KBlockSize = KOneK;
    97 LOCAL_D const TInt KWaitRequestsTableSize = 256;
    98 
    99 LOCAL_D TInt gSecondFileSize = 0;
   100 LOCAL_D TInt gFirstFileSize = 0;
   101 LOCAL_D TInt gCurrentFileSize = 0;
   102 
   103 LOCAL_D TInt64 gMediaSize = 0;
   104 
   105 LOCAL_D TTimeIntervalMicroSeconds gTimeTakenBigFile(0);
   106 LOCAL_D TBuf16<25> gFirstFile;
   107 LOCAL_D TBuf16<25> gSecondFile;
   108 LOCAL_D TBuf16<25> gCurrentFile;
   109 
   110 LOCAL_D TInt gNextFile = 0;
   111 LOCAL_D TTime gTime1;
   112 LOCAL_D TTime gTime2;
   113 _LIT(KMsg1, "1st read timing: %d\n");
   114 _LIT(KMsg2, "2nd read timing: %d\n");
   115 _LIT(KMsg3, "3rd read timing: %d\n");
   116 
   117 LOCAL_D RSemaphore gSync;
   118 
   119 // Concurrent Threads
   120 LOCAL_D RThread gThread1;
   121 LOCAL_D RThread gThread2;
   122 LOCAL_D RSemaphore client;
   123 LOCAL_D const TInt KHeapSize = 0x4000;
   124 LOCAL_D const TInt KMaxHeapSize = 0x100000;
   125 LOCAL_D TBool gPagedRom = EFalse;
   126 
   127 enum TTestState
   128 	{
   129 	EThreadWait,
   130 	EThreadSignal,
   131 	ENoThreads
   132 	};
   133 
   134 /** Formats the drive
   135 
   136 	@param aDrive 	Drive to be formatted
   137 	@param aFormatMode Mode for the format operation
   138 */
   139 LOCAL_C void Formatting(TInt aDrive, TUint aFormatMode )
   140 	{
   141 
   142 	test.Next(_L("Format"));
   143 	TBuf<4> driveBuf = _L("?:\\");
   144 	driveBuf[0]=(TText)(aDrive+'A');
   145 	RFormat format;
   146 	TInt count;
   147 	TInt r = format.Open(TheFs,driveBuf,aFormatMode,count);
   148 	test_KErrNone(r);
   149 	while(count)
   150 		{
   151 		TInt r = format.Next(count);
   152 		test_KErrNone(r);
   153 		}
   154 	format.Close();
   155 	}
   156 
   157 /** Verifies the content of a buffer (all the letters are like the first one)
   158 
   159 	@param aBuffer  Buffer to be verified
   160 
   161 	@return KErrNone if all the letters are the same, KErrCorrupt otherwise
   162 */
   163 LOCAL_C TInt VerifyBuffer(TDes8& aBuffer)
   164 	{
   165 	TChar c = aBuffer[0];
   166 
   167 	for(TInt i = 1; i < aBuffer.Length(); i++)
   168 		{
   169 		if(i%32 != 0)
   170 		{
   171 			if(c != (TChar)(aBuffer[i] - 1))
   172 				return KErrCorrupt;
   173 		}
   174 		else
   175 		{
   176 			if(aBuffer[i] != aBuffer[0])
   177 				return KErrCorrupt;
   178 		}
   179 		c = aBuffer[i];
   180 		}
   181 
   182 	return KErrNone;
   183 	}
   184 
   185 /**  Fills a buffer with character aC, aC+1, aC+2, ..., aC+20, aC, etc
   186 
   187 	@param aBuffer  Buffer to be filled, output
   188 	@param aLength  Length to be filled
   189 	@param aC		Character to be used to fill the buffer
   190 */
   191 LOCAL_C void FillBuffer(TDes8& aBuffer, TInt aLength, TChar aC)
   192 	{
   193 	test (aBuffer.MaxLength() >= aLength);
   194 	for(TInt i = 0; i < aLength; i++)
   195 		{
   196 		aBuffer.Append((i%32) + aC);
   197 		}
   198 	}
   199 
   200 /**  Returns true if fat filesystem present on aDrive
   201 
   202 	@param aFsSession 	Session on the File Server
   203 	@param aDrive 		Drive to be looked at
   204 */
   205 LOCAL_C TBool IsFSFAT(RFs &aFsSession,TInt aDrive)
   206 	{
   207 	TFileName f;
   208 	TInt r = aFsSession.FileSystemName(f,aDrive);
   209 
   210 	if (r != KErrNone)
   211 		{
   212 		test.Printf(_L("Unable to get file system name\n"));
   213 		return EFalse;
   214 		}
   215 
   216 	return (f.CompareF(_L("Fat")) == 0);
   217 	}
   218 
   219 /** Generates a file name of the form FFFFF*<aPos>.TXT (aLong.3)
   220 
   221 	@param aBuffer The filename will be returned here
   222 	@param aLong   Defines the longitude of the file name
   223 	@param aPos	   Defines the number that will be attached to the filename
   224 */
   225 GLDEF_C void FileNameGen(TDes16& aBuffer, TInt aLong, TInt aPos)
   226 {
   227 	TInt padding;
   228 	TInt i = 0;
   229 	TBuf16<10> tempbuf;
   230 
   231 	_LIT(KNumber,"%d");
   232 	tempbuf.Format(KNumber,aPos);
   233 	padding = aLong-tempbuf.Size()/2;
   234 	aBuffer = _L("");
   235 	while(i < padding)
   236 	{
   237 		aBuffer.Append('F');
   238 		i++;
   239 	}
   240 	aBuffer.Append(tempbuf);
   241 
   242 	_LIT(KExtension1, ".TXT");
   243 	aBuffer.Append(KExtension1);
   244 }
   245 
   246 /**  Delete content of directory
   247 
   248 	@param aDir	Target directory
   249 
   250 	@return Error returned if any, otherwise KErrNone
   251 */
   252 LOCAL_C TInt DeleteAll(TDes16& aDir)
   253 {
   254 	TBuf16<100> dir;
   255 	CFileMan* fMan = CFileMan::NewL(TheFs);
   256 	TInt r=0;
   257 
   258 	dir = aDir;
   259 	dir.Append(_L("F*.*"));
   260 	r = fMan->Delete(dir);
   261 
   262 	delete fMan;
   263 	return r;
   264 }
   265 
   266 /**  Waits for all the TRequestStatus in status[] to complete
   267 
   268 	@param status 	Array of TRequestStatus
   269 	@param aLength  Length to be filled
   270 	@param aC		Character to be used to fill the buffer
   271 */
   272 LOCAL_C void WaitForAll(TRequestStatus* status, TInt aSize)
   273 {
   274 	TInt i = 0;
   275 
   276 	RTest test(_L("T_RCACHE"));
   277 
   278 	while(i < aSize)
   279 		{
   280 		User::WaitForRequest(status[i]);
   281 		test(status[i] == KErrNone);
   282 		i++;
   283 		}
   284 
   285 	test.Close();
   286 }
   287 
   288 /**  Reads the parameters from the comand line
   289 	 and updates the appropriate variables
   290 */
   291 LOCAL_C void parseCommandLine()
   292 {
   293 	TBuf<0x100> cmd;
   294 	User::CommandLine(cmd);
   295 	TLex lex(cmd);
   296 	TPtrC token = lex.NextToken();
   297 	TInt r=0;
   298 
   299 	if(token.Length() != 0)
   300 		{
   301 		gDriveToTest = token[0];
   302 		gDriveToTest.UpperCase();
   303 		}
   304 	else
   305 		{
   306 		gDriveToTest = 'C';
   307 		}
   308 
   309 	r = TheFs.CharToDrive(gDriveToTest,gDrive);
   310 	test_KErrNone(r);
   311 	gSessionPath = _L("?:\\F32-TST\\");
   312 	gSessionPath[0] = (TUint16) gDriveToTest;
   313 	test.Printf(_L("\nCLP=%C\n"),(TInt)gDriveToTest);
   314 }
   315 
   316 /**  Writes a file synchronously in blocks of aBlockSize size
   317 
   318 	@param fs			RFs object
   319 	@param aFile		File name
   320 	@param aSize		Size of the file in bytes
   321 	@param aBlockSize	Size of the blocks to be used in bytes
   322 	@param aState		Determines if the operation is being done in the main process
   323 						or in a thread
   324 	@param aReadBack	Reads the file back if ETrue. This is used for Read-ahead testing to ensure
   325 						what is written is also read back through the media driver's cache. If the
   326 						file is bigger than the cache, then subsequent streaming reads starting from
   327 						position zero will have to be re-read from the media.
   328 
   329 	@return Returns KErrNone if everything ok, otherwise it panics
   330 */
   331 LOCAL_C TInt WriteFile(RFs& fs, TDes16& aFile, TInt aSize, TInt aBlockSize, TDes8& aBuf, TTestState aState, TBool aReadBack = EFalse)
   332 {
   333 	RTest test(_L("T_RCACHE"));
   334 
   335 	TInt r = 0;
   336 	RFile fileWrite;
   337 	TInt pos = 0;
   338 
   339 	test(aBlockSize>0);
   340 	test((aSize%aBlockSize) == 0); 	// Ensure the size of the file is a multiple of the block size
   341 
   342 	if(aState == EThreadWait)
   343 	{
   344 		gSync.Wait();
   345 	}
   346 
   347 	// delete file first to ensure it's contents are not in the cache (file may be be on the closed file queue)
   348 	r = fs.Delete(aFile);
   349 	test_Value(r, r == KErrNone || r == KErrNotFound);
   350 
   351 	r = fileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite|EFileReadDirectIO|EFileWriteDirectIO);
   352 	test_KErrNone(r);
   353 
   354 	TInt j = 0;
   355 	while(j < aSize)
   356 		{
   357 			r = fileWrite.Write(pos, aBuf);
   358 			test_KErrNone(r);
   359 
   360 			if (aReadBack)
   361 				{
   362 				r = fileWrite.Read(pos, aBuf);
   363 				test_KErrNone(r);
   364 				}
   365 
   366 			if((j>(aSize/2))&&(aState == EThreadSignal))
   367 			{
   368 				gSync.Signal();
   369 				aState = ENoThreads;
   370 			}
   371 			j += aBlockSize;
   372 			pos += aBlockSize;
   373 		}
   374 	fileWrite.Close();
   375 	test.Close();
   376 
   377 	return KErrNone;
   378 }
   379 
   380 /**  Read File in blocks of size aBlockSize
   381 
   382 	@param fs			RFs object
   383 	@param aFile		File name
   384 	@param aBlockSize	Size of the blocks to be used in bytes
   385 
   386 	@return Returns KErrNone if everything ok, otherwise it panics
   387 */
   388 LOCAL_C TInt ReadFile(RFs& fs, TDes16& aFile, TInt aBlockSize)
   389 {
   390 	RTest test(_L("T_RCACHE"));
   391 
   392 	TInt r = 0, size = 0;
   393 	RFile fileRead;
   394 
   395 	test(aBlockSize>0);				// Block size must be greater than 0
   396 
   397 	r = fileRead.Open(fs,aFile,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff);
   398 	test_KErrNone(r);
   399 
   400 	r = fileRead.Size(size);
   401 	test_KErrNone(r);
   402 
   403 	TInt j = 0;
   404 	while(j < size)
   405 	{
   406 		r = fileRead.Read(gBufReadPtr, aBlockSize);
   407 		test_KErrNone(r);
   408 		j += aBlockSize;
   409 	}
   410 	fileRead.Close();
   411 	test.Close();
   412 
   413 	return KErrNone;
   414 }
   415 
   416 /** Write a file asynchronously in blocks of aBlockSize size
   417 
   418 	@param fs			RFs object
   419 	@param aFileWrite	RFile object, needs to exist beyond the scope of this function
   420 	@param aFile		File name
   421 	@param aSize		Size of the file in bytes
   422 	@param aBlockSize	Size of the blocks to be used in bytes
   423 	@param aStatus		TRequestStatus array for all the requests
   424 */
   425 LOCAL_C void WriteFileAsync(RFs& fs, RFile& aFileWrite, TDes16& aFile, TInt aSize, TInt aBlockSize, TRequestStatus aStatus[])
   426 {
   427 	RTest test(_L("T_RCACHE"));
   428 
   429 	TInt r = 0;
   430 
   431 	test(aBlockSize>0);
   432 	test((aSize%aBlockSize) == 0); 	// Ensure the size of the file is a multiple of the block size
   433 
   434 
   435 	// delete file first to ensure it's contents are not in the cache (file may be be on the closed file queue)
   436 	r = fs.Delete(aFile);
   437 	test(r == KErrNone || r == KErrNotFound);
   438 
   439 	r = aFileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite|EFileReadDirectIO|EFileWriteDirectIO);
   440 	test_KErrNone(r);
   441 
   442 	TInt j = 0, i = 0;
   443 	while(j < aSize)
   444 	{
   445 		aFileWrite.Write(gBufWritePtr,aStatus[i]);
   446 		r = aStatus[i].Int();
   447 		if (r != KErrNone && r != KRequestPending)
   448 			{
   449 			test.Printf(_L("Write %d returned %d\n"), i, r);
   450 			test(0);
   451 			}
   452 		i++;
   453 
   454 		j += aBlockSize;
   455 	}
   456 	test.Close();
   457 }
   458 
   459 /**  Read a file asynchronously in blocks of aBlockSize size
   460 
   461 	@param fs			RFs object
   462 	@param aFileRead	RFile object, needs to exist beyond the scope of this function
   463 	@param aFile		File name
   464 	@param aSize		Size of the file in bytes
   465 	@param aBlockSize	Size of the blocks to be used in bytes
   466 	@param aStatus		TRequestStatus array for all the requests
   467 
   468 	@return KErrNone
   469 */
   470 LOCAL_C TInt ReadFileAsync(RFs& fs,RFile& aFileRead, TDes16& aFile, TInt aBlockSize,TRequestStatus aStatus[], TInt aFileSize)
   471 	{
   472 	RTest test(_L("T_RCACHE"));
   473 
   474 	TInt r = 0;
   475 	TInt size = 0;
   476 
   477 	test(aBlockSize > 0);
   478 
   479 	r = aFileRead.Open(fs,aFile,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff);
   480 	test_KErrNone(r);
   481 
   482 	r = aFileRead.Size(size);
   483 	test_KErrNone(r);
   484 
   485 	test(size == aFileSize);
   486 
   487 	TInt j = 0, i = 0;
   488 	while(j < size)
   489 		{
   490 		aFileRead.Read(gBufReadPtr,aStatus[i]);
   491 		r = aStatus[i].Int();
   492 		if (r != KErrNone && r != KRequestPending)
   493 			{
   494 			test.Printf(_L("Read %d returned %d\n"), i, r);
   495 			test(0);
   496 			}
   497 		i++;
   498 
   499 		j += aBlockSize;
   500 		}
   501 
   502 	test.Close();
   503 	return KErrNone;
   504 	}
   505 
   506 /** Measure the time taken for this file to be written synchronously
   507 */
   508 LOCAL_C TInt WriteTestFile(TDes16& aFile, TInt aSize, TBool aReadBack = EFalse)
   509 {
   510 	RTest test(_L("T_RCACHE"));
   511 
   512 	TTime startTime;
   513 	TTime endTime;
   514 	TInt r = 0;
   515 
   516 	startTime.HomeTime();
   517 
   518 	r = WriteFile(TheFs,aFile, aSize, KBlockSize, gBufWritePtr, ENoThreads, aReadBack);
   519 	test_KErrNone(r);
   520 
   521 	endTime.HomeTime();
   522 
   523 	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
   524 
   525 	test.Close();
   526 	return I64LOW(gTimeTakenBigFile.Int64()) / 1000;
   527 }
   528 
   529 /** Measure the time taken for this file to be read synchronously
   530 */
   531 LOCAL_C TInt ReadTestFile(TDes16& aFile)
   532 {
   533 	TTime startTime;
   534 	TTime endTime;
   535 
   536 	startTime.HomeTime();
   537 	ReadFile(TheFs,aFile, KBlockSize);
   538 	endTime.HomeTime();
   539 
   540 	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
   541 
   542 	return I64LOW(gTimeTakenBigFile.Int64()) / 1000;
   543 }
   544 
   545 /** Read asynchronously the test file from the disc
   546 
   547 */
   548 LOCAL_C TInt ReadAsyncTestFile(TDes16& aFile, TInt aSize)
   549 {
   550 	RTest test(_L("T_RCACHE"));
   551 
   552 	TTime startTime;
   553 	TTime endTime;
   554 	TRequestStatus status[KWaitRequestsTableSize];
   555 	RFs fs;
   556 	RFile file;
   557 
   558 	TInt r = fs.Connect();
   559 	test (r == KErrNone);
   560 
   561 	startTime.HomeTime();
   562 
   563 	ReadFileAsync(fs, file, aFile, KBlockSize, status, aSize);
   564 	WaitForAll(status, aSize/KBlockSize);
   565 
   566 	endTime.HomeTime();
   567 
   568 	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
   569 
   570 	file.Close();
   571 	fs.Close();
   572 	test.Close();
   573 	return I64LOW(gTimeTakenBigFile.Int64()) / 1000;
   574 }
   575 
   576 /** Write a file for the simple case
   577 
   578 */
   579 LOCAL_C TInt WriteFileT(TAny* )
   580 {
   581 	RTest test(_L("T_RCACHE"));
   582 	RFs fs;
   583 	TInt r = fs.Connect();
   584 	test_KErrNone(r);
   585 
   586 	r = fs.SetSessionPath(gSessionPath);
   587 	test_KErrNone(r);
   588 	gTime1.HomeTime();
   589 
   590 	r = WriteFile(fs,gCurrentFile,gCurrentFileSize, KBlockSize,gBufWritePtr, ENoThreads);
   591 	test_KErrNone(r);
   592 
   593 	gTime2.HomeTime();
   594 
   595 	fs.Close();
   596 	test.Close();
   597 
   598 	gTimeTakenBigFile = I64LOW(gTime2.MicroSecondsFrom(gTime1).Int64());
   599 
   600 	client.Signal();
   601 
   602 	return ETrue;
   603 }
   604 
   605 /** Write a file for the concurrent case
   606 
   607 */
   608 LOCAL_C TInt WriteFileT2(TAny* )
   609 {
   610 	RTest test(_L("T_RCACHE"));
   611 	RFs fs;
   612 	TInt r = fs.Connect();
   613 	test_KErrNone(r);
   614 	RFile file;
   615 	TRequestStatus status[KWaitRequestsTableSize];
   616 
   617 
   618 	r = fs.SetSessionPath(gSessionPath);
   619 	test_KErrNone(r);
   620 
   621 	WriteFileAsync(fs,file,gFirstFile,gSecondFileSize, KBlockSize, status);
   622 	WaitForAll(status,gSecondFileSize/KBlockSize);
   623 
   624 	TInt size = 0;
   625 	file.Size(size);
   626 	test( size == gSecondFileSize );
   627 
   628 	file.Close();
   629 	fs.Close();
   630 
   631 	test.Close();
   632 
   633 	client.Signal();
   634 
   635 	return ETrue;
   636 }
   637 
   638 /**  Write a file for the simple case
   639 
   640 */
   641 LOCAL_C TInt ReadFileT(TAny* )
   642 {
   643 	RTest test(_L("T_RCACHE"));
   644 	RFs fs;
   645 	TInt r = fs.Connect();
   646 	test_KErrNone(r);
   647 
   648 	r = fs.SetSessionPath(gSessionPath);
   649 	test_KErrNone(r);
   650 	gTime1.HomeTime();
   651 
   652 	ReadFile(fs,gCurrentFile, KBlockSize);
   653 
   654 	gTime2.HomeTime();
   655 
   656 	fs.Close();
   657 	test.Close();
   658 
   659 	gTimeTakenBigFile = I64LOW(gTime2.MicroSecondsFrom(gTime1).Int64());
   660 
   661 	client.Signal();
   662 
   663 	return ETrue;
   664 }
   665 
   666 /**  Simple case, cache effect shown
   667 
   668 */
   669 LOCAL_C void TestSimpleRead()
   670 {
   671 	TInt r = 0;
   672 	TInt time = 0;
   673 	TInt time2 = 0;
   674 	TInt time3 = 0;
   675 	TInt tcreate = 0;
   676 
   677 	test.Start(_L(""));
   678 
   679 	test.Next(_L("File fits in: read sync + read sync + read async\n"));
   680 
   681 	tcreate = WriteTestFile(gSecondFile, gSecondFileSize);
   682 	test.Printf(_L("Time to create the file: %d ms\n"),tcreate);
   683 
   684 	time = ReadTestFile(gSecondFile);
   685 	test.Printf(KMsg1,time);
   686 	time2 = ReadTestFile(gSecondFile);
   687 	test.Printf(KMsg2,time2);
   688 	time3 = ReadAsyncTestFile(gSecondFile,gSecondFileSize);
   689 	test.Printf(KMsg3,time3);
   690 #if !defined(__WINS__)
   691 	if (gPagedRom)
   692 		test.Printf(_L("Skipping timing test on paged ROM\n"));
   693 	else
   694 		test((time2 <= time) && (time3 < time));
   695 #endif
   696 
   697 	r = DeleteAll(gSessionPath);
   698 	test(r == KErrNone || r == KErrInUse);
   699 
   700 	// Simple case filling/reading the cache from different threads
   701 	test.Next(_L("File fits in: read sync (another thread) + read sync + read async\n"));
   702 	gCurrentFile = gSecondFile;
   703 	gCurrentFileSize = gSecondFileSize;
   704 
   705 	TBuf<20> buf = _L("Write File");
   706 	r = gThread1.Create(buf,WriteFileT,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   707 	test_KErrNone(r);
   708 
   709 	gThread1.Resume();
   710 	client.Wait();
   711 
   712 	tcreate = I64LOW(gTimeTakenBigFile.Int64()) / 1000;
   713 
   714 	test.Printf(_L("Time to create the file from a thread: %d ms\n"),tcreate);
   715 
   716 	buf = _L("Read File");
   717 	r = gThread2.Create(buf,ReadFileT,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   718 	test(r == KErrNone);
   719 
   720 	gThread2.Resume();
   721 	client.Wait();
   722 
   723 	gThread1.Close();
   724 	gThread2.Close();
   725 
   726 	time = I64LOW(gTimeTakenBigFile.Int64()) / 1000;
   727 	test.Printf(KMsg1,time);
   728 	time2 = ReadTestFile(gSecondFile);
   729 	test.Printf(KMsg2,time2);
   730 	time3 = ReadAsyncTestFile(gSecondFile,gSecondFileSize);
   731 	test.Printf(KMsg3,time3);
   732 #if !defined(__WINS__)
   733 	if (gPagedRom)
   734 		test.Printf(_L("Skipping timing test on paged ROM\n"));
   735 	else
   736 		test((time2<=time) && (time3<time));
   737 #endif
   738 
   739 	r = DeleteAll(gSessionPath);
   740 	test(r == KErrNone || r == KErrInUse);
   741 
   742 
   743 	test.Next(_L("File doesn't fit in: read sync + read sync + read async\n"));
   744 
   745 	tcreate = WriteTestFile(gFirstFile,gFirstFileSize);
   746 	test.Printf(_L("Time to create the file: %d ms\n"),tcreate);
   747 
   748 	time = ReadTestFile(gFirstFile);
   749 	test.Printf(KMsg1,time);
   750 	time2 = ReadTestFile(gFirstFile);
   751 	test.Printf(KMsg2,time2);
   752 	time3 = ReadAsyncTestFile(gFirstFile,gFirstFileSize);
   753 	test.Printf(KMsg3,time3);
   754 
   755 	#if !defined(__WINS__)
   756 	// this isn't valid as the file doesn't fit in the cache, so there's no reason why
   757 	// the second read should be any faster than the first
   758 	// test((time2 <= time) && (time3 < time));
   759 	#endif
   760 
   761 
   762 	r = DeleteAll(gSessionPath);
   763 	test(r == KErrNone || r == KErrInUse);
   764 
   765 
   766 	test.Next(_L("File doesn't fit in: read sync (another thread) + read sync + read async\n"));
   767 	gCurrentFile = gFirstFile;
   768 	gCurrentFileSize = gFirstFileSize;
   769 
   770 	buf = _L("Write Big File");
   771 	r = gThread1.Create(buf,WriteFileT,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   772 	test_KErrNone(r);
   773 
   774 	gThread1.Resume();
   775 	client.Wait();
   776 
   777 	tcreate = I64LOW(gTimeTakenBigFile.Int64()) / 1000;
   778 
   779 	test.Printf(_L("Time to create the file from a thread: %d ms\n"),tcreate);
   780 
   781 	buf = _L("Read Big File");
   782 	r = gThread2.Create(buf,ReadFileT,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   783 	test(r == KErrNone);
   784 
   785 	gThread2.Resume();
   786 	client.Wait();
   787 
   788 	gThread1.Close();
   789 	gThread2.Close();
   790 
   791 	time = I64LOW(gTimeTakenBigFile.Int64()) / 1000;
   792 	test.Printf(KMsg1,time);
   793 	time2 = ReadTestFile(gFirstFile);
   794 	test.Printf(KMsg2,time2);
   795 	time3 = ReadAsyncTestFile(gFirstFile,gFirstFileSize);
   796 	test.Printf(KMsg3,time3);
   797 
   798 	#if !defined(__WINS__)
   799 	// this isn't valid as the file doesn't fit in the cache, so there's no reason why
   800 	// the second read should be any faster than the first
   801 	// test((time2 <= time) && (time3 < time));
   802 	#endif
   803 
   804 	r = DeleteAll(gSessionPath);
   805 	test(r == KErrNone || r == KErrInUse);
   806 
   807 	test.End();
   808 }
   809 
   810 /**  Thread to create file and read from it
   811 
   812 */
   813 LOCAL_C TInt ReadAnotherEntry(TAny* )
   814 {
   815 	RTest test(_L("T_RCACHE"));
   816 	RFs fs;
   817 	TInt r = fs.Connect();
   818 	RFile file;
   819 	HBufC8* lBufSec = NULL;
   820 	TPtr8 lBufReadPtr(NULL, 0);
   821 
   822 	TRAPD(res2,lBufSec = HBufC8::NewL(KBlockSize+1));
   823 	test(res2 == KErrNone && lBufSec != NULL);
   824 	lBufReadPtr.Set(lBufSec->Des());
   825 
   826 	test(r == KErrNone);
   827 	r = fs.SetSessionPath(gSessionPath);
   828 
   829 
   830 	// delete file first to ensure it's contents are not in the cache (file may be be on the closed file queue)
   831 	r = fs.Delete(gFirstFile);
   832 	test(r == KErrNone || r == KErrNotFound);
   833 
   834 	r = file.Create(fs,gFirstFile,EFileShareAny|EFileWrite|EFileReadDirectIO|EFileWriteDirectIO);
   835 
   836 	if(r == KErrAlreadyExists)
   837 	{
   838 		r = file.Open(fs,gFirstFile,EFileShareAny|EFileWrite|EFileReadDirectIO|EFileWriteDirectIO);
   839 		test_KErrNone(r);
   840 	}
   841 
   842 	r = file.Write(gBufWritePtr);
   843 	test_KErrNone(r);
   844 
   845 	client.Signal();
   846 
   847 	FOREVER
   848 		{
   849 			r = file.Read(gBufReadPtr, KBlockSize);
   850 			test_KErrNone(r);
   851 		}
   852 
   853 }
   854 
   855 /**  Test the cache behaviour in repeated call situations
   856 
   857 */
   858 LOCAL_C void TestRepeatedRead()
   859 {
   860 	TInt r = 0;
   861 	TInt time = 0;
   862 	TInt i = 0;
   863 	TInt tcreate = 0;
   864 
   865 
   866 	test.Start(_L(""));
   867 	test.Next(_L("File fits in: read sync / read async \n"));
   868 
   869 	tcreate = WriteTestFile(gSecondFile, gSecondFileSize);
   870 	test.Printf(_L("Time to create the file: %d ms\n"),tcreate);
   871 	while(i < 20)
   872 	{
   873 		if(!(i % 2))
   874 		{
   875 			time = ReadTestFile(gSecondFile);
   876 			test.Printf(_L("%d)  Sync Read: %d\n"), i+1 , time);
   877 		}
   878 		else
   879 		{
   880 			time = ReadAsyncTestFile(gSecondFile,gSecondFileSize);
   881 			test.Printf(_L("%d) Async Read: %d\n"), i+1 , time);
   882 		}
   883 		i++;
   884 	}
   885 
   886 	r = DeleteAll(gSessionPath);
   887 	test_KErrNone(r);
   888 
   889 	test.Next(_L("File fits in: read sync / read async, with another thread using the drive \n"));
   890 
   891 	TBuf<20> buf = _L("Noise Thread");
   892 	r = gThread1.Create(buf,ReadAnotherEntry,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   893 	test_KErrNone(r);
   894 
   895 	tcreate = WriteTestFile(gSecondFile, gSecondFileSize);
   896 	test.Printf(_L("Time to create the file: %d ms\n"),tcreate);
   897 
   898 	gThread1.Resume();
   899 	client.Wait();
   900 
   901 	i = 0;
   902 	while(i < 20)
   903 	{
   904 		if(!(i%2))
   905 		{
   906 			time = ReadTestFile(gSecondFile);
   907 			test.Printf(_L("%d)  Sync Read: %d\n"), i+1 , time);
   908 		}
   909 		else
   910 		{
   911 			time = ReadAsyncTestFile(gSecondFile,gSecondFileSize);
   912 			test.Printf(_L("%d) Async Read: %d\n"), i+1 , time);
   913 		}
   914 		i++;
   915 	}
   916 
   917 	gThread1.Kill(KErrNone);
   918 	gThread1.Close();
   919 
   920 	r = DeleteAll(gSessionPath);
   921 	test_KErrNone(r);
   922 
   923 	test.End();
   924 }
   925 
   926 /**  Concurrent operations testing
   927 
   928 */
   929 LOCAL_C void TestConcurrent()
   930 {
   931 	TInt r = 0;
   932 	TInt time = 0;
   933 	TInt time2 = 0;
   934 	TInt time3 = 0;
   935 
   936 	test.Start(_L("Write two files concurrently\n"));
   937 
   938 	gCurrentFile = gSecondFile;
   939 	gCurrentFileSize = gSecondFileSize;
   940 
   941 	TBuf<20> buf = _L("Write Two Files 1");
   942 	r = gThread1.Create(buf,WriteFileT,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   943 	test_KErrNone(r);
   944 
   945 	TBuf<20> buf2 = _L("Write Two Files 2");
   946 	r = gThread2.Create(buf2,WriteFileT2,KDefaultStackSize*2,KHeapSize,KMaxHeapSize,NULL);
   947 	test(r == KErrNone);
   948 
   949 	gThread1.Resume();
   950 	gThread2.Resume();
   951 	client.Wait();
   952 	client.Wait();
   953 
   954 	test.Next(_L("Read the two files repeatedly\n"));
   955 
   956 	test.Printf(_L("File 1:\n"));
   957 	time = ReadTestFile(gSecondFile);
   958 	test.Printf(KMsg1,time);
   959 	time2 = ReadTestFile(gSecondFile);
   960 	test.Printf(KMsg2,time2);
   961 	time3 = ReadAsyncTestFile(gSecondFile,gSecondFileSize);
   962 	test.Printf(KMsg3,time3);
   963 
   964 	test.Printf(_L("File 2:\n"));
   965 
   966 	time = ReadTestFile(gFirstFile);
   967 	test.Printf(KMsg1,time);
   968 	time2 = ReadTestFile(gFirstFile);
   969 	test.Printf(KMsg2,time2);
   970 	time3 = ReadAsyncTestFile(gFirstFile,gSecondFileSize);
   971 	test.Printf(KMsg3,time3);
   972 
   973 	test.End();
   974 
   975 	r = DeleteAll(gSessionPath);
   976 	test_KErrNone(r);
   977 }
   978 
   979 /**  Create file from other thread, to be cached
   980 
   981 */
   982 LOCAL_C TInt CreateFile(TAny* )
   983 {
   984 	RTest test(_L("T_RCACHE"));
   985 	RFs fs;
   986 	TInt r = fs.Connect();
   987 	test(r == KErrNone);
   988 
   989 	r = fs.SetSessionPath(gSessionPath);
   990 	test(r == KErrNone);
   991 
   992 	r = WriteFile(fs, gSecondFile, gSecondFileSize, KBlockSize, gBufWritePtr, EThreadSignal);
   993 	test_KErrNone(r);
   994 
   995 	return KErrNone;
   996 }
   997 
   998 LOCAL_C TBool FindPattern(TUint8 *aBuf, TUint8 *aPattern, TInt aLong, TInt *aOffSet)
   999 {
  1000 	TInt i = 0;
  1001 	TBool found = EFalse;
  1002 
  1003 	while((i < (aLong-4)) && !found)
  1004 	{
  1005 		found = (
  1006 			(aBuf[i] == aPattern[0])&&
  1007 			(aBuf[i+1] == aPattern[1])&&
  1008 			(aBuf[i+2] == aPattern[2])&&
  1009 			(aBuf[i+3] == aPattern[3])
  1010 			);
  1011 	i++;
  1012 	}
  1013 
  1014 	if(found)
  1015 		*aOffSet = --i;
  1016 
  1017 	return found;
  1018 }
  1019 
  1020 /**  Corrupts the second file with Raw access
  1021 
  1022 */
  1023 LOCAL_C void CorruptSecondFileRaw()
  1024 {
  1025 	RRawDisk rDisk;
  1026 	TUint8 gBuffer[4] =
  1027 	{
  1028 		65,66,67,68
  1029 	};
  1030 	TUint8 gBufferB[4] =
  1031 	{
  1032 		33,33,33,33
  1033 	};
  1034 	TPtr8 gBufferBPtr(&gBufferB[0], 4, 4);
  1035 
  1036 	TUint8 gBuffer2[KBlockSize];
  1037 	TPtr8 gBuffer2Ptr(&gBuffer2[0], KBlockSize);
  1038 
  1039 	TInt r = rDisk.Open(TheFs,gDrive);
  1040 	test_KErrNone(r);
  1041 
  1042 	TInt64 pos = 0;
  1043 	TBool found = EFalse;
  1044 	TInt offset = 0;
  1045 
  1046 	while(!found)
  1047 	{
  1048 		rDisk.Read(pos, gBuffer2Ptr);
  1049 		found = FindPattern(gBuffer2, gBuffer, KBlockSize, &offset);
  1050 		pos += (KBlockSize);
  1051 	}
  1052 	pos -= (KBlockSize+1);
  1053 	pos = pos+offset;
  1054 
  1055 	r = rDisk.Write(pos+4, gBufferBPtr);
  1056 	test_KErrNone(r);
  1057 
  1058 	rDisk.Close();
  1059 }
  1060 
  1061 /**  Modifies the second file
  1062 
  1063 */
  1064 LOCAL_C TInt CorruptSecondFile()
  1065 {
  1066 	TInt r = 0;
  1067 	RFile fileWrite;
  1068 	HBufC8* dummy = NULL;
  1069 	TPtr8 dummyPtr(NULL, 0);
  1070 
  1071 	TRAPD(res,dummy = HBufC8::NewL(4));
  1072 	test(res == KErrNone && dummy != NULL);
  1073 
  1074 	dummyPtr.Set(dummy->Des());
  1075 	FillBuffer(dummyPtr, 4, '1');
  1076 
  1077 	r = fileWrite.Open(TheFs,gSecondFile,EFileShareAny|EFileWrite|EFileReadDirectIO|EFileWriteDirectIO);
  1078 	if(r != 0)
  1079 		return r;
  1080 	TInt pos = 30;
  1081 	r = fileWrite.Seek(ESeekStart,pos);
  1082 
  1083 	r = fileWrite.Write(dummyPtr);
  1084 	if(r != 0)
  1085 		return r;
  1086 
  1087 	fileWrite.Close();
  1088 
  1089 	delete dummy;
  1090 
  1091 	return KErrNone;
  1092 }
  1093 
  1094 //
  1095 // Read the file verifying content
  1096 //
  1097 LOCAL_C TInt ReadTestFileVerif(TDes16& aFile, TBool aRaw)
  1098 {
  1099 	TTime startTime;
  1100 	TTime endTime;
  1101 	TInt r = 0, size = 0;
  1102 	RFile fileRead;
  1103 	TInt corrupt = 0;
  1104 	TBool isFat=IsFSFAT(TheFs,gDrive);
  1105 
  1106 	startTime.HomeTime();
  1107 
  1108 	r = fileRead.Open(TheFs,aFile,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff);
  1109 	test_KErrNone(r);
  1110 
  1111 	r = fileRead.Size(size);
  1112 	test_KErrNone(r);
  1113 
  1114 	TInt j = 0;
  1115 	while(j < size)
  1116 		{
  1117 			r = fileRead.Read(gBufReadPtr, KBlockSize);
  1118 			if(aRaw)
  1119 			{
  1120 				if(isFat)
  1121 				{
  1122 					test_KErrNone(r);
  1123 				}
  1124 				else
  1125 				{
  1126 				if(r == KErrCorrupt)
  1127 					corrupt++;
  1128 				}
  1129 			}
  1130 			else
  1131 			{
  1132 				test_KErrNone(r);
  1133 			}
  1134 			j += KBlockSize;
  1135 			r = VerifyBuffer(gBufReadPtr);
  1136 			if(r == KErrCorrupt)
  1137 				corrupt++;
  1138 		}
  1139 
  1140 	fileRead.Close();
  1141 
  1142 	test(corrupt>0); // Ensure the cache returns the changed content
  1143 
  1144 	endTime.HomeTime();
  1145 
  1146 	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
  1147 
  1148 	return I64LOW(gTimeTakenBigFile.Int64()) / 1000;
  1149 }
  1150 
  1151 
  1152 /** Negative testing
  1153 
  1154 */
  1155 LOCAL_C void TestNegative()
  1156 {
  1157 	TInt r = 0;
  1158 	TInt time, time2, time3;
  1159 	TInt tcreate = 0;
  1160 
  1161 	test.Start(_L(""));
  1162 	// Kill a thread while writing, then read content
  1163 	TBuf<20> buf = _L("A thread to kill");
  1164 	gCurrentFile = gSecondFile;
  1165 	gCurrentFileSize = gSecondFileSize;
  1166 
  1167 	r = gThread1.Create(buf,CreateFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
  1168 	test_KErrNone(r);
  1169 
  1170 	gThread1.Resume();
  1171 	gSync.Wait();
  1172 	gThread1.Kill(KErrGeneral);
  1173 	gThread1.Close();
  1174 	test.Next(_L("Read after killing the write in the middle\n"));
  1175 	time = ReadTestFile(gSecondFile);
  1176 	test.Printf(KMsg1,time);
  1177 	time2 = ReadTestFile(gSecondFile);
  1178 	test.Printf(KMsg2,time2);
  1179 
  1180 	// Read async the content
  1181 	TInt size = 0;
  1182 	TRequestStatus status[KWaitRequestsTableSize];
  1183 	TTime startTime;
  1184 	TTime endTime;
  1185 	RFile fileRead;
  1186 
  1187 	startTime.HomeTime();
  1188 
  1189 	r = fileRead.Open(TheFs,gSecondFile,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff);
  1190 	test_KErrNone(r);
  1191 
  1192 	r = fileRead.Size(size);
  1193 	test_KErrNone(r);
  1194 
  1195 	TInt j = 0, i = 0;
  1196 	while(j < size)
  1197 		{
  1198 			fileRead.Read(gBufReadPtr,status[i++]);
  1199 			test_KErrNone(r);
  1200 			j += KBlockSize;
  1201 		}
  1202 
  1203 	j = i;
  1204 	i = 0;
  1205 	while(i < j)
  1206 	{
  1207 		User::WaitForRequest(status[i++]);
  1208 	}
  1209 	fileRead.Close();
  1210 	endTime.HomeTime();
  1211 	gTimeTakenBigFile = I64LOW(endTime.MicroSecondsFrom(startTime).Int64());
  1212  	time3 = I64LOW(gTimeTakenBigFile.Int64()) / 1000;
  1213 
  1214 	test.Printf(KMsg3,time3);
  1215 
  1216 	// Modify file in some position
  1217 	test.Next(_L("Overwrite partially a file\n"));
  1218 	Formatting(gDrive, EFullFormat);
  1219 	r = TheFs.MkDirAll(gSessionPath);
  1220 	if (r != KErrNone && r != KErrAlreadyExists)
  1221 		{
  1222 		test_KErrNone(r);
  1223 		}
  1224 
  1225 	tcreate = WriteTestFile(gSecondFile, gSecondFileSize);
  1226 	test.Printf(_L("Time to create the file: %d ms\n"),tcreate);
  1227 
  1228 	time = ReadTestFile(gSecondFile);
  1229 	test.Printf(KMsg1,time);
  1230 
  1231 	time = ReadTestFile(gSecondFile);
  1232 	test.Printf(KMsg2,time);
  1233 
  1234 	CorruptSecondFile();
  1235 
  1236 	time = ReadTestFileVerif(gSecondFile,EFalse);
  1237 	test.Printf(KMsg1,time);
  1238 
  1239 	time = ReadTestFileVerif(gSecondFile,EFalse);
  1240 	test.Printf(KMsg2,time);
  1241 
  1242 	// Modify the file in disk, raw access
  1243 	test.Next(_L("Overwrite file with raw access\n"));
  1244 
  1245 	Formatting(gDrive,EFullFormat);
  1246 
  1247 	r = TheFs.MkDirAll(gSessionPath);
  1248 	if (r != KErrNone && r != KErrAlreadyExists)
  1249 		{
  1250 		test_KErrNone(r);
  1251 		}
  1252 
  1253 
  1254 	tcreate = WriteTestFile(gSecondFile, gSecondFileSize);
  1255 	test.Printf(_L("Time to create the file: %d ms\n"),tcreate);
  1256 
  1257 	time = ReadTestFile(gSecondFile);
  1258 	test.Printf(KMsg1,time);
  1259 
  1260 	time = ReadTestFile(gSecondFile);
  1261 	test.Printf(KMsg2,time);
  1262 
  1263 	CorruptSecondFileRaw();
  1264 
  1265 	time = ReadTestFileVerif(gSecondFile,ETrue);
  1266 	test.Printf(KMsg1,time);
  1267 
  1268 	time = ReadTestFileVerif(gSecondFile,ETrue);
  1269 	test.Printf(KMsg2,time);
  1270 
  1271 
  1272 	r = DeleteAll(gSessionPath);
  1273 	test_KErrNone(r);
  1274 
  1275 	test.End();
  1276 }
  1277 
  1278 /**  Creates the files to fill the read cache
  1279 
  1280 	@param aFiles 	 Number of files needed to fill the cache
  1281 	@param aFileSize The file size
  1282 */
  1283 LOCAL_C void CreateFiles(TInt aFiles, TInt aFileSize)
  1284 {
  1285 	TInt i = 0, r = 0;
  1286 	RFile file;
  1287 	TBuf16<50> directory;
  1288 
  1289 	TBuf16<50> path;
  1290 	TBuf16<50> buffer(50);
  1291 
  1292 	directory = gSessionPath;
  1293 
  1294 	test.Printf(_L("Creating %d files for filling the cache (size %d)\n"), aFiles, aFileSize);
  1295 
  1296 	// create a big buffer to speed things up
  1297 	HBufC8* bigBuf = NULL;
  1298 	const TInt KBigBifferSize = 32 * 1024;
  1299 	TRAPD(res,bigBuf = HBufC8::NewL(KBigBifferSize));
  1300 	test(res == KErrNone && bigBuf != NULL);
  1301 
  1302 	TPtr8 bigBufWritePtr(NULL, 0);
  1303 	bigBufWritePtr.Set(bigBuf->Des());
  1304 	FillBuffer(bigBufWritePtr, KBigBifferSize, 'A');
  1305 
  1306 
  1307 	i = 0;
  1308 	while(i < aFiles)
  1309 	{
  1310 		if (i % 10 == 0)
  1311 			test.Printf(_L("Creating file %d of %d...\r"), i, aFiles);
  1312 		FileNameGen(buffer, 8, i+3) ;
  1313 		path = directory;
  1314 		path.Append(buffer);
  1315 
  1316 		// delete file first to ensure it's contents are not in the cache (file may be on the closed file queue)
  1317 		r = TheFs.Delete(path);
  1318 		test(r == KErrNone || r == KErrNotFound);
  1319 
  1320 		r = file.Create(TheFs,path,EFileShareAny|EFileWrite|EFileReadDirectIO|EFileWriteDirectIO);
  1321 		if(r == KErrAlreadyExists)
  1322 			r = file.Open(TheFs,path,EFileShareAny|EFileWrite|EFileReadDirectIO|EFileWriteDirectIO);
  1323 		TInt j = 0;
  1324 		while(j < aFileSize)
  1325 			{
  1326 			bigBufWritePtr.SetLength(Min(KBigBifferSize, aFileSize - j));
  1327 			r = file.Write(bigBufWritePtr);
  1328 			test_KErrNone(r);
  1329 			j += bigBufWritePtr.Length();
  1330 			}
  1331 
  1332 		file.Close();
  1333 		i++;
  1334 	}
  1335 	test.Printf(_L("\nFiles created\n"));
  1336 	delete bigBuf;
  1337 }
  1338 
  1339 /**  Fills the read cache
  1340 
  1341 	@param aFile	 Array of files needed to fill the cache
  1342 	@param aFiles 	 Number of files needed to fill the cache
  1343 	@param aFileSize The file size
  1344 */
  1345 LOCAL_C void FillCache(RFile aFile[KFilesNeededToFillCache], TInt aFiles, TInt aFileSize)
  1346 {
  1347 	TInt i = 0, r = 0;
  1348 	TBuf16<50> directory;
  1349 
  1350 	TBuf16<50> path;
  1351 	TBuf16<50> buffer(50);
  1352 	HBufC8* buf = NULL;
  1353 	TPtr8 bufPtr(NULL, 0);
  1354 
  1355 	TRAPD(res,buf = HBufC8::NewL(2));
  1356 	test(res == KErrNone && buf != NULL);
  1357 	bufPtr.Set(buf->Des());
  1358 
  1359 	directory = gSessionPath;
  1360 
  1361 	i = 0;
  1362 	while(i < aFiles)
  1363 	{
  1364 		FileNameGen(buffer, 8, i+3) ;
  1365 		path = directory;
  1366 		path.Append(buffer);
  1367 		r = aFile[i].Open(TheFs,path,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOff);
  1368 		test_KErrNone(r);
  1369 
  1370 		TInt j = 0;
  1371 		while(j < aFileSize)
  1372 			{
  1373 				r = aFile[i].Read(j,bufPtr);
  1374 				test_KErrNone(r);
  1375 				j += 4*KOneK;
  1376 			}
  1377 
  1378 		i++;
  1379 	}
  1380 
  1381 	delete buf;
  1382 	test.Printf(_L("Cache filled\n"));
  1383 }
  1384 
  1385 /** Fills the default cache
  1386 
  1387 */
  1388 LOCAL_C void TestFillCache()
  1389 {
  1390 	TInt nFiles = KFilesNeededToFillCache;
  1391 	TInt fSize = KDefaultCacheSize;
  1392 	RFile file[KFilesNeededToFillCache];
  1393 
  1394 	if(gMediaSize> ((fSize * nFiles)+gSecondFileSize+gFirstFileSize))
  1395 	{
  1396 		test.Start(_L("Creating files for filling the cache\n"));
  1397 		CreateFiles(nFiles,fSize);
  1398 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
  1399 		// get number of items on Page Cache
  1400 		TFileCacheStats startPageCacheStats;
  1401 		TInt r = controlIo(TheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats);
  1402 		test(r==KErrNone || r == KErrNotSupported);
  1403 		test.Printf(_L("Number of page cache lines on free list at beginning=%d\n"),startPageCacheStats.iFreeCount);
  1404 		test.Printf(_L("Number of page cache lines on used list at beginning=%d\n"),startPageCacheStats.iUsedCount);
  1405 		test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue);
  1406 #endif
  1407 		FillCache(file,nFiles,fSize);
  1408 
  1409 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
  1410 		// get number of items on Page Cache
  1411 		r = controlIo(TheFs,gDrive, KControlIoFileCacheStats, startPageCacheStats);
  1412 		test(r==KErrNone || r == KErrNotSupported);
  1413 		test.Printf(_L("Number of page cache lines on free list at end=%d\n"),startPageCacheStats.iFreeCount);
  1414 		test.Printf(_L("Number of page cache lines on used list at end=%d\n"),startPageCacheStats.iUsedCount);
  1415 		test.Printf(_L("Number of files on closed queue=%d\n"),startPageCacheStats.iFilesOnClosedQueue);
  1416 #endif
  1417 		TestSimpleRead();
  1418 
  1419 		TInt i = 0;
  1420 		while( i < KFilesNeededToFillCache )
  1421 			{
  1422 			file[i++].Close();
  1423 			}
  1424 
  1425 		test.End();
  1426 	}
  1427 	else
  1428 		test.Printf(_L("Skipping the fill of the cache due to lack of space in the current drive\n"));
  1429 }
  1430 
  1431 /**	Overflow-safe tick deltas
  1432 
  1433 */
  1434 static TInt64 TicksToMsec(TUint32 aInitTicks, TUint32 aFinalTicks, TInt aFastCounterFreq)
  1435 	{
  1436 	TUint32 timeDelta;
  1437 	if (aFinalTicks >= aInitTicks)
  1438 		timeDelta = aFinalTicks - aInitTicks;
  1439 	else
  1440 		timeDelta = aFinalTicks + (KMaxTUint32 - aInitTicks);		// must've wrapped
  1441 
  1442 	return TInt64(timeDelta) * TInt64(1000000) / TInt64(aFastCounterFreq);
  1443 	}
  1444 
  1445 /** Read three blocks and waits for the read ahead on the File Server to do its job
  1446 
  1447 */
  1448 LOCAL_C void TestReadAhead()
  1449 {
  1450 	TInt r = 0,tcreate;
  1451 	RFile fileRead;
  1452 	HBufC8* dummy = NULL;
  1453 	TPtr8 dummyPtr(NULL, 0);
  1454 
  1455 	TUint32 initTicks = 0;
  1456 	TUint32 finalTicks = 0;
  1457 	TTimeIntervalMicroSeconds timeTakenReadFirst(0);
  1458 	TTimeIntervalMicroSeconds timeTakenReadSubsequent(0);
  1459 
  1460 	// On NAND/FAT and NOR/LFFS drives, due to the lack of DMA support, the read-ahead is likely to happen
  1461 	// BEFORE control is returned to this test app - for NAND this could be fixed by adding
  1462 	// "FileCacheReadAsync OFF" to the estart.txt file, but we can't do this on the integrator as it has no
  1463 	// estart.txt file. Also, we can't set "FileCacheReadAsync OFF" for LFFS as it kills the LFFS background
  1464 	// processing (!)
  1465 	// So... it's only really worth testing on MMC.
  1466 	_LIT(KFATName,"FAT");
  1467 	TDriveInfo driveInfo;
  1468 	test(TheFs.Drive(driveInfo, gDrive) == KErrNone);
  1469 	TFileName fileSystem;
  1470 	r = TheFs.FileSystemName(fileSystem, gDrive);
  1471 	fileSystem.UpperCase();
  1472 	test((r==KErrNone)||(r==KErrNotFound));
  1473 	// ONLY test on MMC
  1474 	if ((driveInfo.iType != EMediaHardDisk) || (fileSystem.Compare(KFATName) != 0))
  1475 		{
  1476 		test.Printf(_L("Skipping read-ahead testing (drive is not MMC)...\n"));
  1477 		return;
  1478 		}
  1479 
  1480 	//--Find out if the drive is sync/async at this point and print information
  1481     TPckgBuf<TBool> drvSyncBuf;
  1482     r = TheFs.QueryVolumeInfoExt(gDrive, EIsDriveSync, drvSyncBuf);
  1483     test(r == KErrNone);
  1484 	const TBool bDrvSync = drvSyncBuf();
  1485     if(bDrvSync)
  1486 		test.Printf(_L("Drive D: is synchronous\n"));
  1487 	else
  1488 		test.Printf(_L("Drive D: is asynchronous\n"));
  1489 
  1490 	// use a fast counter as this is more accurate than using TTime
  1491 	TInt fastCounterFreq;
  1492 	r = HAL::Get(HAL::EFastCounterFrequency, fastCounterFreq);
  1493 	test(r == KErrNone);
  1494 	test.Printf(_L("HAL::EFastCounterFrequency %d\n"), fastCounterFreq);
  1495 
  1496 	// Bind this thread to CPU 0. This is so that timer deltas don't drift from
  1497 	// scheduling - else, it causes spurious failures.
  1498 	if (UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0) > 1)
  1499 		(void)UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)0, 0);
  1500 
  1501 	const TInt KReadLen = 28 * KOneK;
  1502 
  1503 	TRAPD(res,dummy = HBufC8::NewL(KReadLen));
  1504 	test(res == KErrNone && dummy != NULL);
  1505 
  1506 	dummyPtr.Set(dummy->Des());
  1507 
  1508 	test.Start(_L("Creating test file..."));
  1509 
  1510 
  1511 	tcreate = WriteTestFile(gFirstFile, gFirstFileSize, ETrue);
  1512 	test.Printf(_L("Time to create the file: %d ms\n"),tcreate);
  1513 
  1514 	r = fileRead.Open(TheFs,gFirstFile,EFileShareAny|EFileRead|EFileReadBuffered|EFileReadAheadOn);
  1515 	test_KErrNone(r);
  1516 
  1517 	// Read #1
  1518 	test.Printf(_L("Issuing read #1...\n"));
  1519 	initTicks = User::FastCounter();
  1520 	r = fileRead.Read(dummyPtr);
  1521 	finalTicks = User::FastCounter();
  1522 	test_KErrNone(r);
  1523 
  1524 	timeTakenReadFirst = TicksToMsec(initTicks, finalTicks, fastCounterFreq);
  1525 	test.Printf(_L("first read time %d \n"), I64LOW(timeTakenReadFirst.Int64()));
  1526 
  1527 	// Read #2
  1528 	test.Printf(_L("Issuing read #2...\n"));
  1529 	r = fileRead.Read(dummyPtr);
  1530 
  1531 	// Read #3
  1532 	test.Printf(_L("Issuing read #3......resulting in read-ahead #1\n"));
  1533 	r = fileRead.Read(dummyPtr);
  1534 
  1535 	// Wait for the read ahead #1 to be done - this should be approx the same size as previous read (KReadLen)
  1536 	test.Printf(_L("Wait for read-ahead #1...\n"));
  1537 	User::After(I64LOW(timeTakenReadFirst.Int64()) * 3 / 2);
  1538 
  1539 
  1540 	test.Printf(_L("Issuing read #4...resulting in read-ahead #2\n"));
  1541 	initTicks = User::FastCounter();
  1542 	r = fileRead.Read(dummyPtr);
  1543 	finalTicks = User::FastCounter();
  1544 	test_KErrNone(r);
  1545 	timeTakenReadSubsequent = TicksToMsec(initTicks, finalTicks, fastCounterFreq);
  1546 
  1547 	test.Printf(_L("read time:  %d \n"), I64LOW(timeTakenReadSubsequent.Int64()));
  1548 
  1549 #if !defined(__WINS__)
  1550 	// NB the read-ahead on LFFS occurs "synchronously" i.e. it occurs before control is returned
  1551 	// to the caller. However it's not a good idea to mark the drive as synchronous (FileCacheReadAsync OFF)
  1552 	// as this causes the drive thread's priority to be lowered which kills the LFFS background processing (!)
  1553 	if (gPagedRom)
  1554 		test.Printf(_L("Skipping timing test on paged ROM\n"));
  1555 	else
  1556 		test(timeTakenReadSubsequent.Int64() < timeTakenReadFirst.Int64());
  1557 #endif
  1558 
  1559 	// The read ahead #2 should now be in progress - this should be approx KReadLen * 2
  1560 	// so this read will take result in the next read taking longer than normal (about double)
  1561 	test.Printf(_L("Issuing read #5......resulting in read-ahead #3\n"));
  1562 	initTicks = User::FastCounter();
  1563 	r = fileRead.Read(dummyPtr);
  1564 	finalTicks = User::FastCounter();
  1565 	test_KErrNone(r);
  1566 	timeTakenReadSubsequent = TicksToMsec(initTicks, finalTicks, fastCounterFreq);
  1567 	test.Printf(_L("read time:  %d\n"), I64LOW(timeTakenReadSubsequent.Int64()));
  1568 
  1569 
  1570 	// this read should take a long time, so don't test
  1571 //#if !defined(__WINS__)
  1572 //	test(gTimeTakenReadBlockFile.Int64() < gTimeTakenBigFile.Int64());
  1573 //#endif
  1574 
  1575 	// The third read should be very quick as the previous read-ahead should have already buffered the data
  1576 	test.Printf(_L("Issuing read #6......resulting in read-ahead #4\n"));
  1577 	initTicks = User::FastCounter();
  1578 	r = fileRead.Read(dummyPtr);
  1579 	finalTicks = User::FastCounter();
  1580 	test_KErrNone(r);
  1581 	timeTakenReadSubsequent = TicksToMsec(initTicks, finalTicks, fastCounterFreq);
  1582 	test.Printf(_L("read time:  %d\n"), I64LOW(timeTakenReadSubsequent.Int64()));
  1583 
  1584 
  1585 #if !defined(__WINS__)
  1586 	if (gPagedRom)
  1587 		test.Printf(_L("Skipping timing test on paged ROM\n"));
  1588 	else
  1589 		test(timeTakenReadSubsequent.Int64() < timeTakenReadFirst.Int64());
  1590 #endif
  1591 
  1592 
  1593 	fileRead.Close();
  1594 
  1595 	r = DeleteAll(gSessionPath);
  1596 	test_KErrNone(r);
  1597 
  1598 	delete dummy;
  1599 	test.End();
  1600 
  1601 }
  1602 
  1603 /** Main tests function
  1604 */
  1605 GLDEF_C void CallTestsL()
  1606 	{
  1607 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
  1608 	test.Printf(_L("Disabling Lock Fail simulation ...\n"));
  1609 	// turn OFF lock failure mode
  1610 	TBool simulatelockFailureMode = EFalse;
  1611 	TInt r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode);
  1612 	test (r == KErrNone);
  1613 #endif
  1614 
  1615 	TBuf16<45> dir;
  1616 
  1617 	RProcess().SetPriority(EPriorityBackground);
  1618 
  1619 	// FileNames/File generation
  1620 	test.Start(_L("Preparing the environmnet\n"));
  1621 	FileNameGen(gFirstFile, 8, gNextFile++);
  1622 	FileNameGen(gSecondFile, 8, gNextFile++);
  1623 	dir = gSessionPath;
  1624 	dir.Append(gFirstFile);
  1625 	gFirstFile = dir;
  1626 	dir = gSessionPath;
  1627 	dir.Append(gSecondFile);
  1628 	gSecondFile = dir;
  1629 
  1630 
  1631 	TRAPD(res,gBuf = HBufC8::NewL(KBlockSize+1));
  1632 	test(res == KErrNone && gBuf != NULL);
  1633 
  1634 	gBufWritePtr.Set(gBuf->Des());
  1635 	FillBuffer(gBufWritePtr, KBlockSize, 'A');
  1636 
  1637 	TRAPD(res2,gBufSec = HBufC8::NewL(KBlockSize+1));
  1638 	test(res2 == KErrNone && gBufSec != NULL);
  1639 	gBufReadPtr.Set(gBufSec->Des());
  1640 
  1641 	test.Next(_L("Negative test\n"));
  1642 	TestNegative();
  1643 
  1644 	test.Next(_L("Simple cases, use of the cache from same location/different"));
  1645 	TestSimpleRead();
  1646 
  1647 	test.Next(_L("Repeated reads, same file\n"));
  1648 	TestRepeatedRead();
  1649 
  1650 	test.Next(_L("Read ahead testing\n"));
  1651 	TestReadAhead();
  1652 
  1653 	test.Next(_L("Concurrent read cases\n"));
  1654 	TestConcurrent();
  1655 
  1656 	test.Next(_L("Fill the cache, boundary testing\n"));
  1657 	TestFillCache();
  1658 
  1659 	test.End();
  1660 	delete gBuf;
  1661 	delete gBufSec;
  1662 
  1663 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
  1664 	// turn lock failure mode back ON (if enabled)
  1665 	simulatelockFailureMode = ETrue;
  1666 	r = controlIo(TheFs, gDrive, KControlIoSimulateLockFailureMode, simulatelockFailureMode);
  1667 	test (r == KErrNone);
  1668 #endif
  1669 
  1670 	}
  1671 
  1672 /** Initialises semaphores and call the tests
  1673 */
  1674 LOCAL_C void DoTests()
  1675 	{
  1676 	TInt r = 0;
  1677 
  1678 	r = client.CreateLocal(0);
  1679  	test_KErrNone(r);
  1680 
  1681   	r = gSync.CreateLocal(0);
  1682  	test_KErrNone(r);
  1683 
  1684 
  1685 	r = TheFs.SetSessionPath(gSessionPath);
  1686 	test_KErrNone(r);
  1687 
  1688 	r = TheFs.MkDirAll(gSessionPath);
  1689 	if (r != KErrNone && r != KErrAlreadyExists)
  1690 		{
  1691 		test_KErrNone(r);
  1692 		}
  1693 	TheFs.ResourceCountMarkStart();
  1694 	TRAP(r,CallTestsL());
  1695 	if (r == KErrNone)
  1696 		TheFs.ResourceCountMarkEnd();
  1697 	else
  1698 		{
  1699 		test_KErrNone(r);
  1700 		}
  1701 	}
  1702 
  1703 /** Determines the space that can be used for the files
  1704 
  1705 */
  1706 TBool CheckForDiskSize()
  1707 {
  1708 	TVolumeInfo volInfo;
  1709 	TInt r = TheFs.Volume(volInfo, gDrive);
  1710 	test_KErrNone(r);
  1711 	gMediaSize = volInfo.iSize;
  1712 	gSecondFileSize = KBlockSize*92;
  1713 	gFirstFileSize = KBlockSize*(256);
  1714 	while(((2*gFirstFileSize)+KOneMeg) > gMediaSize )
  1715 		{
  1716 			gFirstFileSize -= (2*KBlockSize);
  1717 		}
  1718 
  1719 	TReal32 small = (TReal32)(gSecondFileSize/KOneK);
  1720 	TReal32 big = (TReal32)(gFirstFileSize/KOneK);
  1721 
  1722 	test.Printf(_L("Test File: %.2f KB\n"), small );
  1723 	test.Printf(_L("Too big for the cache file: %.2f KB (%.2f MB)\n"), big, big / KOneK );
  1724 
  1725 	if(gFirstFileSize < gSecondFileSize)
  1726 		return EFalse;
  1727 	else
  1728 		return ETrue;
  1729 }
  1730 
  1731 /** Main function
  1732 
  1733 	@return KErrNone if everything was ok, panics otherwise
  1734 */
  1735 GLDEF_C TInt E32Main()
  1736     {
  1737 	// Determine whether this is a paged ROM -
  1738 	// if it is we bypass some of the timimg tests as the default paging ROMs have a deliberately
  1739 	// small pool of pages (in order to stress the system) and reading things through the file cache
  1740 	// in this "artificial" environment can cause code to be evicted which can result in the read timings
  1741 	// going AWOL. In a more real-world environment, file caching should turn itself off if the amount of
  1742 	// memory falls below a threshold.
  1743 #if !defined(__WINS__)
  1744 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
  1745 	gPagedRom = romHeader->iPageableRomStart ? (TBool)ETrue : (TBool)EFalse;
  1746 #endif
  1747 
  1748 	RThread t;
  1749 	gMainThreadId = t.Id();
  1750 
  1751 	CTrapCleanup* cleanup;
  1752 	cleanup = CTrapCleanup::New();
  1753 
  1754 	__UHEAP_MARK;
  1755 	test.Start(_L("Starting tests... T_RCACHE"));
  1756 	parseCommandLine();
  1757 
  1758 	TInt r = TheFs.Connect();
  1759 	test_KErrNone(r);
  1760 
  1761 	TDriveInfo info;
  1762 	TVolumeInfo volInfo;
  1763 	r = TheFs.Drive(info,gDrive);
  1764 	test_KErrNone(r);
  1765 
  1766 	if(info.iMediaAtt&KMediaAttVariableSize)
  1767 		{
  1768 		test.Printf(_L("Tests skipped in RAM drive\n"));
  1769 		goto out;
  1770 		}
  1771 
  1772 	r = TheFs.Volume(volInfo, gDrive);
  1773 	if (r == KErrNotReady)
  1774 		{
  1775 		if (info.iType == EMediaNotPresent)
  1776 			test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)gDriveToTest);
  1777 		else
  1778 			test.Printf(_L("%c: medium found (type %d) but drive not ready\nPrevious test may have hung; else, check hardware.\n"), (TUint)gDriveToTest, (TInt)info.iType);
  1779 		}
  1780 	else if (r == KErrCorrupt)
  1781 		{
  1782 		test.Printf(_L("%c: Media corruption; previous test may have aborted; else, check hardware\n"), (TUint)gDriveToTest);
  1783 		}
  1784 	test_KErrNone(r);
  1785 
  1786 	if(!(volInfo.iFileCacheFlags & (EFileCacheReadEnabled | EFileCacheReadAheadEnabled)))
  1787 		{
  1788 		test.Printf(_L("Skipping tests, Read caching not enabled in this drive\n"));
  1789 		goto out;
  1790 		}
  1791 	
  1792 	if (((volInfo.iDrive.iMediaAtt & KMediaAttFormattable)))
  1793 		Formatting(gDrive,ESpecialFormat);
  1794 
  1795 	if(CheckForDiskSize())
  1796 		{
  1797 		DoTests();
  1798 		}
  1799 	else
  1800 		{
  1801 		test.Printf(_L("Skipping tests due to lack of space to perform them in this drive\n"));
  1802 		}
  1803 out:
  1804 	test.End();
  1805 
  1806 	TheFs.Close();
  1807 	test.Close();
  1808 
  1809 	__UHEAP_MARKEND;
  1810 	delete cleanup;
  1811 	return(KErrNone);
  1812     }
  1813