kerneltest/f32test/fsstress/t_soak1.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1999-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\fsstress\t_soak1.cpp
       
    15 // Suggestions for future improvements: The createVerifyFileX method uses local 
       
    16 // RBufs for writing and reading. By making these buffers global (at least the 
       
    17 // write buffers), the overhead of allocating and filling memory can be avoided.
       
    18 // 
       
    19 //
       
    20 
       
    21 #include <f32file.h>
       
    22 #include <e32test.h>
       
    23 #include "t_chlffs.h"
       
    24 #include "t_server.h"
       
    25 #define __TESTING_LFFS__
       
    26 
       
    27 LOCAL_D TInt gDriveNumber;
       
    28 
       
    29 const TInt KMaxNumberThreads     = 4;
       
    30 const TInt KHeapSize             = 0x600000;
       
    31 const TInt KDiskUnitThreshold    = 0x1000000; // if disk metrics are above threshold, display in MB rather than KB
       
    32 const TInt KNotificationInterval = 10 * 1000000;
       
    33 
       
    34 const TInt KMaxSizeArray         = 3;
       
    35 const TInt KMaxFilesPerDirectory = 100;
       
    36 
       
    37 struct TTestMetrics
       
    38 	{
       
    39 	TInt SizeArray[KMaxSizeArray][5];
       
    40 	TInt KSpaceRequiredForMakeAndDelete;
       
    41 	TInt KFillDiskFileSize;
       
    42 	};
       
    43 
       
    44 
       
    45 
       
    46 
       
    47 ///#define SINGLE__THREAD
       
    48 
       
    49 // 256 sectors, 17 sectors+1, 3 bytes, 254 sectors+4, 100 sectors
       
    50 //  50 sectors, 113 sectors+25, 10 sectors, 103 bytes, 199 sectors+44
       
    51 // 24 sectors+166, 189 bytes, 225 sectors, 4 sectors+221, 117 sectors+40
       
    52 LOCAL_D const TTestMetrics DefMetrics =
       
    53 				{
       
    54 				{{65536,4353,3,65028,25600},	// Sizearray[0]
       
    55 				{12800,28953,2560,103,50988},	// Sizearray[1]
       
    56 				{6310,189,57600,1245,29992}},	// Sizearray[2]
       
    57 				655360,							// KSpaceRequiredForMakeAndDelete
       
    58 				65536							// KFillDiskFileSize
       
    59 				};
       
    60 
       
    61 // 16 sectors, 1 sectors+1, 3 bytes, 15 sectors+4, 6 sectors
       
    62 //  3 sectors, 7 sectors+25, 1 sector, 103 bytes, 12 sectors+44
       
    63 // 2 sectors+166, 189 bytes, 15 sectors, 4 sectors+221, 7 sectors+40
       
    64 LOCAL_D const TTestMetrics LffsMetrics = 
       
    65 				{
       
    66 				{{4096,257,3,3844,1536},		// Sizearray[0]
       
    67 				{768,1817,256,103,3116},		// Sizearray[1]
       
    68 				{678,189,3840,1245,1832}},		// Sizearray[2]
       
    69 				36864,							// KSpaceRequiredForMakeAndDelete
       
    70 				4096							// KFillDiskFileSize
       
    71 				};
       
    72 
       
    73 // 1600 sectors, 100 sectors+100, 1 sector+44, 1501 sectors+144, 600 sectors
       
    74 // 300 sectors, 709 sectors+196, 100 sectors, 40 sectors+60, 1217 sectors+48
       
    75 // 264 sectors+216, 73 sectors+212, 486 sectors+84, 715 sectors+160
       
    76 LOCAL_D const TTestMetrics FAT32Metrics =
       
    77 				{
       
    78 				{{409600,25700,300,384400,153600},		// Sizearray[0]
       
    79 				{76800,181700,25600,10300,311600},		// Sizearray[1]
       
    80 				{67800,18900,384000,124500,183200}},	// Sizearray[2]
       
    81 				3686400,								// KSpaceRequiredForMakeAndDelete
       
    82 				409600									// KFillDiskFileSize
       
    83 				};
       
    84 
       
    85 // 8 sectors, 1 sectors+1, 3 bytes, 7 sectors+4, 3 sectors
       
    86 //  1 sectors, 3 sectors+25, 1 sector, 103 bytes, 6 sectors+44
       
    87 // 1 sector+166 bytes, 189 bytes, 7 sectors, 2 sectors+221, 3 sectors+40
       
    88 
       
    89 LOCAL_D const TTestMetrics NandMetrics = 
       
    90 				{
       
    91 				{{2048,257,3,1796,768},			// Sizearray[0]
       
    92 				{256,793,256,103,1580},			// Sizearray[1]
       
    93 				{422,189,1792,833,808}},		// Sizearray[2]
       
    94 				20480,							// KSpaceRequiredForMakeAndDelete
       
    95 				2048							// KFillDiskFileSize
       
    96 				};
       
    97 
       
    98 
       
    99 
       
   100 LOCAL_D const TTestMetrics* TheMetrics = 0;
       
   101 
       
   102 
       
   103 #if defined(__WINS__)
       
   104 #define WIN32_LEAN_AND_MEAN
       
   105 #pragma warning (disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
       
   106 #pragma warning (default:4201) // warning C4201: nonstandard extension used : nameless struct/union
       
   107 #endif
       
   108 
       
   109 #if defined(_UNICODE)
       
   110 	#if !defined(UNICODE)
       
   111 		#define UNICODE
       
   112 	#endif
       
   113 #endif
       
   114 
       
   115 #ifndef SINGLE__THREAD
       
   116 	#define REUSE_THREAD
       
   117 #endif
       
   118 
       
   119 #ifdef REUSE_THREAD
       
   120 	LOCAL_D TBool gRequestEnd;
       
   121 #endif
       
   122 
       
   123 class TThreadTestInfo
       
   124 	{
       
   125 public:
       
   126 	TInt iCycles;
       
   127 	TInt iErrors;
       
   128 	TInt iSizeArrayPos;
       
   129 	TInt iErrorInfo;
       
   130 	};
       
   131 
       
   132 GLDEF_D RTest test(_L("T_SOAK1"));
       
   133 LOCAL_D TThreadTestInfo ThreadTestInfo[KMaxNumberThreads];
       
   134 LOCAL_D TBool CurrentlyFillingDisk;
       
   135 LOCAL_D TInt FillDiskCount;
       
   136 LOCAL_D TInt FillDiskCycle;
       
   137 
       
   138 LOCAL_C TInt MakeAndDeleteFilesThread(TAny* anId);
       
   139 LOCAL_C TInt FillAndEmptyDiskThread(TAny* anId);
       
   140 LOCAL_C TInt CreateVerifyFileX(const TDesC& aBaseName,TInt aSize,RFs &aFs,TInt aPattern);
       
   141 LOCAL_C TInt MakeFileName(TInt aThreadId, TInt aFileNumber, RFs & aFs, TFileName& aName, TBool aMakeDir = ETrue);
       
   142 LOCAL_C TInt AppendPath(TFileName& aPath, TInt aNumber, TInt aLevel);
       
   143 
       
   144 _LIT( KConnect, "Connect" );
       
   145 _LIT( KDelete, "Delete" );
       
   146 _LIT( KDriveToChar, "DriveToChar" );
       
   147 _LIT( KAppendPath, "AppendPath" );
       
   148 _LIT( KSetSessPath, "SetSessPath" );
       
   149 _LIT( KMdAll, "MkdirAll" );
       
   150 _LIT( KVolInfo, "VolInfo" );
       
   151 _LIT( KReplace, "Replace" );
       
   152 _LIT( KRead, "Read" );
       
   153 _LIT( KWrite, "Write" );
       
   154 _LIT( KFlush, "Flush" );
       
   155 _LIT( KDataCompare, "DataCompare" );
       
   156 _LIT( KMemory, "Memory" );
       
   157 _LIT( KFilePrefix, "FILE_" );
       
   158 
       
   159 _LIT(KPath, "?:\\SOAK_TEST\\SESSION%d\\");
       
   160 
       
   161 LOCAL_C void LogError( TInt aError, const TDesC& aAction, const TDesC& aFileName, TUint a1, TUint a2, TInt line = -1 )
       
   162 	{
       
   163 	if(line >= 0)
       
   164 		{
       
   165 		_LIT(KFmt, "TSOAK1 ERROR (line %d): %d, file [%S], %S, (0x%x, 0x%x)");
       
   166 		RDebug::Print(KFmt, line, aError, &aFileName, &aAction, a1, a2);
       
   167 		}
       
   168 	else 
       
   169 		{
       
   170 		_LIT(KFmt, "TSOAK1 ERROR: %d, file [%S], %S, (0x%x, 0x%x)");
       
   171 		RDebug::Print(KFmt, aError, &aFileName, &aAction, a1, a2);
       
   172 		}
       
   173 	}
       
   174 
       
   175 LOCAL_C TInt MakeFileName(TInt aThreadId, TInt aFileNumber, RFs & aFs, TFileName& aName, TBool aMakeDir)
       
   176 //
       
   177 // creates a file name and makes all the directory components, if required
       
   178 //
       
   179 	{
       
   180 	
       
   181 	TFileName path;
       
   182 	path.Format(KPath, aThreadId);
       
   183 	
       
   184 	TChar driveLetter;
       
   185 	TInt  r;
       
   186 	r = aFs.DriveToChar(gDriveNumber, driveLetter);
       
   187 	if (r != KErrNone)
       
   188 		{
       
   189 		LogError(r, KDriveToChar, KNullDesC, driveLetter, 0);
       
   190 		aFs.Close();
       
   191 		return(r);
       
   192 		}
       
   193 		
       
   194 	path[0] = (TText) driveLetter;
       
   195 	r = aFs.SetSessionPath(path);
       
   196 	if (r != KErrNone)
       
   197 		{
       
   198 		LogError(r, KSetSessPath, path, 0, 0);
       
   199 		aFs.Close();
       
   200 		return(r);
       
   201 		}
       
   202 		
       
   203 	// add additional directories
       
   204 	TInt fileNumber;
       
   205 	fileNumber = aFileNumber;
       
   206 	r = AppendPath(path, fileNumber, 0);
       
   207 	if(r != KErrNone)
       
   208 		{
       
   209 		LogError(r, KAppendPath, path, fileNumber, 0);
       
   210 		aFs.Close();
       
   211 		return(r);
       
   212 		}
       
   213 		
       
   214 	if(aMakeDir)
       
   215 		{
       
   216 		r = aFs.MkDirAll(path);
       
   217 		if (r != KErrNone && r != KErrAlreadyExists)
       
   218 			{
       
   219 			LogError(r, KMdAll, path, 0, 0);
       
   220 			aFs.Close();
       
   221 			return(r);
       
   222 			}
       
   223 		}
       
   224 		
       
   225 	// and finally add file name
       
   226 	path.Append(KFilePrefix);
       
   227 	path.AppendNum(aFileNumber);
       
   228 
       
   229 	aName = path;
       
   230 	return(KErrNone);
       
   231 	}
       
   232 	
       
   233 
       
   234 LOCAL_C TInt AppendPath(TFileName& aPath, TInt aNumber, TInt aLevel)
       
   235 //
       
   236 // helper function for MakeFileName()
       
   237 //
       
   238 	{
       
   239 	
       
   240 	if(aNumber > KMaxFilesPerDirectory)
       
   241 		{
       
   242 		aNumber /= KMaxFilesPerDirectory;
       
   243 		AppendPath(aPath, aNumber, aLevel + 1);
       
   244 		}
       
   245 		
       
   246 	if(aLevel)
       
   247 		{	
       
   248 		aPath.AppendNum(aNumber % KMaxFilesPerDirectory);	
       
   249 		aPath.Append('\\');	
       
   250 		}
       
   251 	
       
   252 	return(KErrNone);
       
   253 	}
       
   254 
       
   255 LOCAL_C TInt MakeAndDeleteFilesThread(TAny* anId)
       
   256 //
       
   257 // The entry point for the 'MakeAndDeleteFiles' thread.
       
   258 //
       
   259 	{
       
   260 
       
   261 	TInt thrdId=(TInt)anId;
       
   262 	TInt pattern=(ThreadTestInfo[thrdId].iCycles)%2;
       
   263     TInt r;
       
   264 	RFs f;
       
   265 	r=f.Connect();
       
   266 	if (r!=KErrNone)
       
   267 		{
       
   268 		LogError( r, KConnect, KNullDesC, 0, 0 );
       
   269 		ThreadTestInfo[thrdId].iErrorInfo=1;
       
   270 		return(r);
       
   271 		}
       
   272 
       
   273 	TFileName fileName;
       
   274 	TInt sizeArrayPos = ThreadTestInfo[thrdId].iSizeArrayPos;
       
   275 #ifdef REUSE_THREAD
       
   276 	while(!gRequestEnd)
       
   277 		{
       
   278 #endif	
       
   279 		for(TInt i = 0; i < 5; i++)
       
   280 			{
       
   281 			// create files
       
   282 			r = MakeFileName(thrdId, i, f, fileName);
       
   283 			if(r != KErrNone)
       
   284 				{
       
   285 				ThreadTestInfo[thrdId].iErrorInfo=2;
       
   286 				f.Close();
       
   287 				return(r);
       
   288 				}
       
   289 			
       
   290 			r = CreateVerifyFileX(fileName, TheMetrics->SizeArray[sizeArrayPos][0], f, pattern);
       
   291 			if (r!=KErrNone)
       
   292 				{
       
   293 				ThreadTestInfo[thrdId].iErrorInfo=3;
       
   294 				f.Close();
       
   295 				return(r);
       
   296 				}
       
   297 			
       
   298 			// delete selected files at certain points in the cycle
       
   299 			TInt deleteFile = EFalse;
       
   300 			switch(i)
       
   301 				{
       
   302 				default:
       
   303 					// nothing to be done
       
   304 				break;
       
   305 				case 2:
       
   306 					// delete file 0
       
   307 					deleteFile = ETrue;
       
   308 					r = MakeFileName(thrdId, 0, f, fileName, EFalse);
       
   309 				break;
       
   310 				case 3:
       
   311 					// delete file 1
       
   312 					deleteFile = ETrue;
       
   313 					r = MakeFileName(thrdId, 1, f, fileName, EFalse);
       
   314 				break;
       
   315 				}
       
   316 				
       
   317 				if(deleteFile)
       
   318 					{
       
   319 					// check MakeFileName() error code
       
   320 					if(r != KErrNone)
       
   321 						{
       
   322 						ThreadTestInfo[thrdId].iErrorInfo = 4;
       
   323 						f.Close();
       
   324 						return(r);
       
   325 						}
       
   326 						
       
   327 					// and delete file
       
   328 					r = f.Delete(fileName);
       
   329 					if(r != KErrNone)
       
   330 						{
       
   331 						ThreadTestInfo[thrdId].iErrorInfo = 5;
       
   332 						f.Close();
       
   333 						return(r);
       
   334 						}
       
   335 					}
       
   336 			}
       
   337 			
       
   338 		sizeArrayPos++;
       
   339 		if(sizeArrayPos >= KMaxSizeArray)
       
   340 			{
       
   341 			sizeArrayPos = 0;
       
   342 			}
       
   343 			
       
   344 		ThreadTestInfo[thrdId].iSizeArrayPos=sizeArrayPos;
       
   345 #ifdef REUSE_THREAD
       
   346 	ThreadTestInfo[thrdId].iCycles++;
       
   347 	pattern = (ThreadTestInfo[thrdId].iCycles) % 2;
       
   348 	}
       
   349 #endif
       
   350 
       
   351 	f.Close();
       
   352 	return(KErrNone);
       
   353 	}
       
   354 
       
   355 LOCAL_C TInt FillAndEmptyDiskThread(TAny* anId)
       
   356 //
       
   357 // The entry point for the 'FillAndEmptyDisk' thread.
       
   358 //
       
   359 	{
       
   360 
       
   361 	TInt thrdId=(TInt)anId;
       
   362 	TInt pattern=(ThreadTestInfo[thrdId].iCycles)%2;
       
   363     TInt r;
       
   364 	RFs f;
       
   365 	r=f.Connect();
       
   366 	if (r!=KErrNone)
       
   367 		{
       
   368 		LogError( r, KConnect, KNullDesC, 0, 0 );
       
   369 		ThreadTestInfo[thrdId].iErrorInfo=6;
       
   370 		return(r);
       
   371 		}
       
   372 
       
   373 	TInt i;
       
   374 #ifdef REUSE_THREAD
       
   375 	while(!gRequestEnd)
       
   376 		{
       
   377 #endif	
       
   378 		for (i=0;i<5;i++) // Create/Delete 5 files each time
       
   379 			{
       
   380 			if (CurrentlyFillingDisk)
       
   381 				{
       
   382 				TVolumeInfo v;
       
   383 				r=f.Volume(v,gDriveNumber);
       
   384 				if (r!=KErrNone)
       
   385 					{
       
   386 					ThreadTestInfo[thrdId].iErrorInfo=7;
       
   387 					LogError( r, KVolInfo, KNullDesC, gDriveNumber, 0);
       
   388 					f.Close();
       
   389 					return(r);
       
   390 					}
       
   391 				if (v.iFree<=(TheMetrics->KSpaceRequiredForMakeAndDelete+TheMetrics->KFillDiskFileSize))
       
   392 					CurrentlyFillingDisk=EFalse;
       
   393 				else
       
   394 					{
       
   395 					TFileName fileName;
       
   396 					r = MakeFileName(thrdId, FillDiskCount, f, fileName);
       
   397 					if(r != KErrNone)
       
   398 						{
       
   399 						ThreadTestInfo[thrdId].iErrorInfo = 8;
       
   400 						f.Close();
       
   401 						return(r);
       
   402 						}			
       
   403 					
       
   404 					r = CreateVerifyFileX(fileName, TheMetrics->KFillDiskFileSize, f, pattern);
       
   405 					if (r!=KErrNone)
       
   406 						{
       
   407 						ThreadTestInfo[thrdId].iErrorInfo=9;
       
   408 						f.Close();
       
   409 						return(r);
       
   410 						}
       
   411 					FillDiskCount++;
       
   412 					}
       
   413 				}
       
   414 			else
       
   415 				{
       
   416 				if (FillDiskCount<=0)
       
   417 					{
       
   418 					CurrentlyFillingDisk=ETrue;
       
   419 					FillDiskCount=0;
       
   420 					FillDiskCycle++;
       
   421 					}
       
   422 				else
       
   423 					{
       
   424 					FillDiskCount--;
       
   425 					TFileName fileName;
       
   426 					r = MakeFileName(thrdId, FillDiskCount, f, fileName, EFalse);
       
   427 					if(r != KErrNone)
       
   428 						{
       
   429 						ThreadTestInfo[thrdId].iErrorInfo = 10;
       
   430 						f.Close();
       
   431 						return(r);
       
   432 						}
       
   433 					
       
   434 					r = f.Delete(fileName);				
       
   435 					if (r!=KErrNone)
       
   436 						{
       
   437 						ThreadTestInfo[thrdId].iErrorInfo=11;
       
   438 						LogError(r, KDelete, fileName,FillDiskCount, 0);
       
   439 						f.Close();
       
   440 						return(r);
       
   441 						}
       
   442 					}
       
   443 				}
       
   444 			}
       
   445 #ifdef REUSE_THREAD
       
   446 		ThreadTestInfo[thrdId].iCycles++;
       
   447 		pattern = (ThreadTestInfo[thrdId].iCycles) % 2;
       
   448 		}			
       
   449 #endif
       
   450 
       
   451 	f.Close();
       
   452 	return(KErrNone);
       
   453 	}
       
   454 
       
   455 const TInt KCreateFileBufSize = 0x80000; 
       
   456 LOCAL_C TInt CreateVerifyFileX(const TDesC& aFileName, TInt aSize, RFs& aFs, TInt aPattern)
       
   457 //
       
   458 // Create and verify a file.
       
   459 //
       
   460 	{
       
   461 	// Note, the directory structure is provided by MakeFileName(). Hence it 
       
   462 	// is assumed at this point that the path to the file exists already.
       
   463 	RFile file;
       
   464 	TInt r;
       
   465 	r = file.Replace(aFs, aFileName, EFileWrite);
       
   466 	if (r!=KErrNone)
       
   467 		{
       
   468 		LogError( r, KReplace, aFileName, EFileWrite, 0 );
       
   469 		return(r);
       
   470 		}
       
   471 
       
   472 	// Grow it to the specified size by writing a pattern buffer to it
       
   473 	// Alternate the pattern buffer each time
       
   474 	RBuf8 wBuf;
       
   475 	r = wBuf.CreateMax(KCreateFileBufSize);
       
   476 	if(r != KErrNone)
       
   477 		{
       
   478 		LogError(r, KMemory, aFileName, 0, 0, __LINE__);
       
   479 		wBuf.Close();
       
   480 		file.Close();
       
   481 		return(r);
       
   482 		}
       
   483 		
       
   484 	TInt i;
       
   485 	
       
   486 	if (aPattern)
       
   487 		{
       
   488 		// ascending pattern
       
   489 		for (i = 0; i < KCreateFileBufSize; i++)
       
   490 			{			
       
   491 			wBuf[i] = (TUint8) i;			
       
   492 			}
       
   493 		}
       
   494 	else
       
   495 		{
       
   496 		// descending pattern
       
   497 		for (i = 0; i < KCreateFileBufSize; i++)
       
   498 			{
       
   499 			wBuf[i] = (TUint8) ((KCreateFileBufSize - 1) - i);
       
   500 			}
       
   501 		}
       
   502 
       
   503 
       
   504 	TInt pos;
       
   505 	TInt chunkSize;
       
   506 	TInt sectorCount = 0;
       
   507 	
       
   508 	for (pos = 0; pos < aSize; pos += chunkSize)
       
   509 		{
       
   510 		wBuf[0]=(TUint8)i;	// Insert sector count
       
   511 		chunkSize = Min((aSize-pos), KCreateFileBufSize);
       
   512 		r = file.Write(pos, wBuf, chunkSize);
       
   513 		if (r != KErrNone)
       
   514 			{
       
   515 			LogError(r, KWrite, aFileName, pos, chunkSize, __LINE__);
       
   516 			file.Close();
       
   517 			wBuf.Close();
       
   518 			return(r);
       
   519 			}
       
   520 			
       
   521 		sectorCount++;
       
   522 		}
       
   523 
       
   524 	// Flush it
       
   525 	r=file.Flush();
       
   526 	if (r!=KErrNone)
       
   527 		{
       
   528 		LogError( r, KFlush, aFileName, 0, 0, __LINE__);
       
   529 		file.Close();
       
   530 		wBuf.Close();
       
   531 		return(r);
       
   532 		}
       
   533 
       
   534 //	Test still works if this is commented out just doesn't verify
       
   535 	// Read back and verify it
       
   536 	RBuf8 rBuf;
       
   537 	r = rBuf.CreateMax(KCreateFileBufSize);
       
   538 	if(r != KErrNone)
       
   539 		{
       
   540 		LogError( r, KMemory, aFileName, 0, 0, __LINE__);
       
   541 		file.Close();
       
   542 		wBuf.Close();
       
   543 		rBuf.Close();
       
   544 		return(KErrGeneral);
       
   545 		}
       
   546 	
       
   547 	
       
   548 	for (pos = 0;pos < aSize; pos += chunkSize)
       
   549 		{
       
   550 		chunkSize = Min((aSize-pos), KCreateFileBufSize);
       
   551 		r = file.Read(pos, rBuf, chunkSize);
       
   552 		if (r != KErrNone)
       
   553 			{
       
   554 			LogError(r, KRead, aFileName, pos, 0, __LINE__);
       
   555 			file.Close();
       
   556 			wBuf.Close();
       
   557 			rBuf.Close();
       
   558 			return(r);
       
   559 			}
       
   560 			
       
   561 		wBuf[0] = (TUint8) i; // Insert sector count
       
   562 		wBuf.SetLength(chunkSize);
       
   563 		r = rBuf.Compare(wBuf);
       
   564 		if (r != 0)
       
   565 			{
       
   566 			LogError(r, KDataCompare, aFileName, 0, 0, __LINE__);
       
   567 			file.Close();
       
   568 			wBuf.Close();
       
   569 			rBuf.Close();
       
   570 			return(KErrGeneral);
       
   571 			}
       
   572 		}
       
   573 //
       
   574 
       
   575 	file.Close();
       
   576 	wBuf.Close();
       
   577 	rBuf.Close();
       
   578 	return(KErrNone);
       
   579 	}
       
   580 	
       
   581 
       
   582 #ifdef SINGLE__THREAD
       
   583 LOCAL_C void DoTests()
       
   584 //
       
   585 //  single thread
       
   586 //
       
   587     {
       
   588 
       
   589 	TInt r=KErrNone;
       
   590 	test.Next(_L("Start continuous file Write/Read/Verify operation"));
       
   591 	RThread t[KMaxNumberThreads];
       
   592 	TRequestStatus tStat[KMaxNumberThreads];
       
   593 
       
   594 	TInt i=0;
       
   595 
       
   596 	TName threadName;
       
   597 	TRequestStatus kStat=KRequestPending;
       
   598 	test.Console()->Read(kStat);
       
   599 	ThreadTestInfo[i].iCycles=0;
       
   600 	ThreadTestInfo[i].iErrors=0;
       
   601 	ThreadTestInfo[i].iSizeArrayPos=(i%KMaxSizeArray);
       
   602 	ThreadTestInfo[i].iErrorInfo=0;
       
   603 	if (i<(KMaxNumberThreads-1))
       
   604 		{
       
   605 		threadName.Format(_L("MakeAndDeleteFiles%d"),i);
       
   606     	r=t[i].Create(threadName,MakeAndDeleteFilesThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)i);
       
   607 		}
       
   608 	else
       
   609 		{
       
   610 		// Last thread fills/empties disk
       
   611 		threadName.Format(_L("FillAndEmptyDisk%d"),i);
       
   612     	r=t[i].Create(threadName,FillAndEmptyDiskThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)i);
       
   613 		}
       
   614 	if (r!=KErrNone)
       
   615 		test.Printf(_L("Error(%d) creating thread(%d)\r\n"),r,i);
       
   616 	test(r==KErrNone);
       
   617 	t[i].Logon(tStat[i]);
       
   618 	t[i].Resume();
       
   619 	CurrentlyFillingDisk=ETrue;
       
   620 	FillDiskCount=0;
       
   621 
       
   622     TInt totalTime=0;
       
   623     TTime startTime;
       
   624     TTime time;
       
   625     startTime.UniversalTime();
       
   626 
       
   627 	TInt ypos=test.Console()->WhereY();
       
   628 	FOREVER
       
   629 		{
       
   630 		User::WaitForAnyRequest();
       
   631 		if (kStat!=KRequestPending)
       
   632 			{
       
   633     		t[i].LogonCancel(tStat[i]);
       
   634 			User::WaitForRequest(tStat[i]);
       
   635 			break;
       
   636 			}
       
   637 		else
       
   638 			{
       
   639 			TBool threadFinished=EFalse;
       
   640 			if (tStat[i]!=KRequestPending && !threadFinished)
       
   641 				{
       
   642 				t[i].Close();
       
   643 				(ThreadTestInfo[i].iCycles)++;
       
   644 				if (tStat[i]!=KErrNone)
       
   645 					(ThreadTestInfo[i].iErrors)++;
       
   646 				threadFinished=ETrue;
       
   647 
       
   648 				// Launch another thread
       
   649 				TInt threadNameId=((ThreadTestInfo[i].iCycles)%2)?(i+KMaxNumberThreads):i; // Alternate thread name
       
   650 				threadName.Format(_L("FillAndEmptyDisk%d"),threadNameId);
       
   651    				r=t[i].Create(threadName,FillAndEmptyDiskThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)i);
       
   652 				if (r!=KErrNone)
       
   653 					test.Printf(_L("Error(%d) creating thread(%d)\r\n"),r,i);
       
   654     			test(r==KErrNone);
       
   655     			t[i].Logon(tStat[i]);
       
   656 				t[i].Resume();
       
   657 				}
       
   658 				
       
   659 			test.Console()->SetPos(0,(ypos+i));
       
   660 			test.Printf(_L("Thread(%d): % 4d errors in % 4d cycles (%d)\r\n"),i,ThreadTestInfo[i].iErrors,ThreadTestInfo[i].iCycles,ThreadTestInfo[i].iErrorInfo);
       
   661 			if (!threadFinished)
       
   662 				{
       
   663 				test.Printf(_L("Semaphore death"));
       
   664 				break;
       
   665 				}
       
   666 			TVolumeInfo v;
       
   667 			r=TheFs.Volume(v,gDriveNumber);
       
   668 			test(r==KErrNone);
       
   669 			test.Console()->SetPos(0,(ypos+KMaxNumberThreads));
       
   670 			test.Printf(_L("Free space on disk: %u K(of %u K)\r\n"),(v.iFree/1024).Low(),(v.iSize/1024).Low());
       
   671 
       
   672             TTimeIntervalSeconds timeTaken;
       
   673             time.UniversalTime();
       
   674             r=time.SecondsFrom(startTime,timeTaken);
       
   675             test(r==KErrNone);
       
   676             totalTime=timeTaken.Int();
       
   677 
       
   678             TInt seconds = totalTime % 60;
       
   679             TInt minutes = (totalTime / 60) % 60;
       
   680             TInt hours   = (totalTime / 3600) % 24;
       
   681             TInt days    = totalTime / (60 * 60 * 24);
       
   682             test.Printf(_L("Elapsed Time: %d d %02d:%02d:%02d\r\n"), days, hours, minutes, seconds);
       
   683 			}
       
   684 		}
       
   685     }
       
   686 
       
   687 #else 
       
   688 
       
   689 LOCAL_C void DoTests()
       
   690 //
       
   691 //  multiple threads
       
   692 //
       
   693     {
       
   694 
       
   695 	TInt r=KErrNone;
       
   696 	test.Next(_L("Start continuous file Write/Read/Verify operation"));
       
   697 	RThread t[KMaxNumberThreads];
       
   698 	TRequestStatus tStat[KMaxNumberThreads];
       
   699 
       
   700 	TInt i=0;
       
   701 
       
   702 	TName threadName;
       
   703 	TRequestStatus kStat=KRequestPending;
       
   704 	test.Console()->Read(kStat);
       
   705 	for (i=0;i<KMaxNumberThreads;i++)
       
   706 		{
       
   707 		ThreadTestInfo[i].iCycles=0;
       
   708 		ThreadTestInfo[i].iErrors=0;
       
   709 		ThreadTestInfo[i].iSizeArrayPos=(i%KMaxSizeArray);
       
   710 		ThreadTestInfo[i].iErrorInfo=0;
       
   711 		if (i<(KMaxNumberThreads-1))
       
   712 			{
       
   713 			threadName.Format(_L("MakeAndDeleteFiles%d"),i);
       
   714 	    	r=t[i].Create(threadName,MakeAndDeleteFilesThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)i);
       
   715 			}
       
   716 		else
       
   717 			{
       
   718 			// Last thread fills/empties disk
       
   719 			threadName.Format(_L("FillAndEmptyDisk%d"),i);
       
   720 	    	r=t[i].Create(threadName,FillAndEmptyDiskThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)i);
       
   721 			}
       
   722 		if (r!=KErrNone)
       
   723    			test.Printf(_L("Error(%d) creating thread(%d)\r\n"),r,i);
       
   724 	    test(r==KErrNone);
       
   725 	    t[i].Logon(tStat[i]);
       
   726 		t[i].Resume();
       
   727 		}
       
   728 	CurrentlyFillingDisk=ETrue;
       
   729 	FillDiskCount=0;
       
   730 
       
   731     TInt totalTime = 0;
       
   732     TTime cycleTime;
       
   733     TTime startTime;
       
   734     TTime time;
       
   735     startTime.UniversalTime();
       
   736     cycleTime.UniversalTime();
       
   737     
       
   738 	TVolumeInfo v;
       
   739 	r=TheFs.Volume(v,gDriveNumber);
       
   740 	test(r==KErrNone);
       
   741 //	TInt initialFreeSpace = I64LOW(v.iFree / 1024);
       
   742 
       
   743 #ifdef __LIMIT_EXECUTION_TIME__
       
   744 	RTimer timer;
       
   745 	timer.CreateLocal();
       
   746 	TRequestStatus reqStat;
       
   747 	timer.After(reqStat,60000000); // After 60 secs
       
   748 #endif
       
   749 
       
   750 #ifdef REUSE_THREAD
       
   751 	RTimer displayTimer;
       
   752 	displayTimer.CreateLocal();
       
   753 	TRequestStatus displayStat;
       
   754 	displayTimer.After(displayStat, KNotificationInterval); // after 10 secs
       
   755 #endif
       
   756 
       
   757 	TInt ypos=test.Console()->WhereY();
       
   758 	FOREVER
       
   759 		{
       
   760 		User::WaitForAnyRequest();
       
   761 		if (kStat!=KRequestPending)
       
   762 			{
       
   763 			// user requested to end - let threads die
       
   764 #ifdef REUSE_THREAD				
       
   765 			gRequestEnd = ETrue;
       
   766 #endif			
       
   767 			for (i=0;i<KMaxNumberThreads;i++)
       
   768 				{
       
   769 				User::WaitForRequest(tStat[i]);
       
   770 				}
       
   771 			break;
       
   772 			}
       
   773 #ifdef __LIMIT_EXECUTION_TIME__
       
   774 		else if (reqStat != KRequestPending)
       
   775 			{
       
   776 			// max execution exceeded - wait for threads to die
       
   777 			TInt totalCycles = 0;
       
   778 			for (i=0;i<KMaxNumberThreads;i++)
       
   779 				{
       
   780 				totalCycles+= ThreadTestInfo[i].iCycles;
       
   781 				}
       
   782 			test.Printf(_L("Total cycles = %d\r\n"), totalCycles);
       
   783 			test.Printf(_L("Waiting for thread death...\r\n"));
       
   784 			for (i=0;i<KMaxNumberThreads;i++)
       
   785 				{
       
   786 				User::WaitForRequest(tStat[i]);
       
   787 				}
       
   788 			break;
       
   789 			}
       
   790 #endif
       
   791 		else
       
   792 			{
       
   793 			// other notification
       
   794 			TBool threadFinished=EFalse;
       
   795 			for (i=0;i<KMaxNumberThreads;i++)
       
   796 				{
       
   797 				if (tStat[i]!=KRequestPending && !threadFinished)
       
   798 					{
       
   799 					t[i].Close();
       
   800 					(ThreadTestInfo[i].iCycles)++;
       
   801 					if (tStat[i]!=KErrNone)
       
   802 						(ThreadTestInfo[i].iErrors)++;
       
   803 					threadFinished=ETrue;
       
   804 
       
   805 					// Launch another thread
       
   806 					TInt threadNameId=((ThreadTestInfo[i].iCycles)%2)?(i+KMaxNumberThreads):i; // Alternate thread name
       
   807 					if (i<(KMaxNumberThreads-1))
       
   808 						{
       
   809 						threadName.Format(_L("MakeAndDeleteFiles%d"),threadNameId);
       
   810 	    				r=t[i].Create(threadName,MakeAndDeleteFilesThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)i);
       
   811 						}
       
   812 					else
       
   813 						{
       
   814 						// Last thread fills/empties disk
       
   815 						threadName.Format(_L("FillAndEmptyDisk%d"),threadNameId);
       
   816 	    				r=t[i].Create(threadName,FillAndEmptyDiskThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)i);
       
   817 						}
       
   818 					if (r!=KErrNone)
       
   819    						test.Printf(_L("Error(%d) creating thread(%d)\r\n"),r,i);
       
   820 	    			test(r==KErrNone);
       
   821 	    			t[i].Logon(tStat[i]);
       
   822 					t[i].Resume();
       
   823 					}
       
   824 				test.Console()->SetPos(0,(ypos+i));
       
   825    				test.Printf(_L("Thread(%d): % 4d errors in % 4d cycles (%d)\r\n"),i,ThreadTestInfo[i].iErrors,ThreadTestInfo[i].iCycles,ThreadTestInfo[i].iErrorInfo);
       
   826 				}
       
   827 				
       
   828 #ifdef REUSE_THREAD
       
   829 			if(displayStat != KRequestPending)
       
   830 				{
       
   831 				// re-request notification
       
   832 				displayTimer.After(displayStat, KNotificationInterval);
       
   833 				}
       
   834 			else if (!threadFinished)
       
   835 				{
       
   836 				test.Printf(_L("Semaphore death"));
       
   837 				break;
       
   838 				}
       
   839 #else 
       
   840 			if (!threadFinished)
       
   841 				{
       
   842 				test.Printf(_L("Semaphore death"));
       
   843 				break;
       
   844 				}
       
   845 #endif					
       
   846 				
       
   847 			r=TheFs.Volume(v,gDriveNumber);
       
   848 			test(r==KErrNone);
       
   849 			test.Console()->SetPos(0,(ypos+KMaxNumberThreads));
       
   850 			
       
   851 			TInt  freeSpace;
       
   852 			TInt8 freeSpaceUnit;
       
   853 			TInt  totalSpace;
       
   854 			TInt8 totalSpaceUnit;
       
   855 			
       
   856 			// switch t
       
   857 			if(v.iFree > KDiskUnitThreshold)
       
   858 				{
       
   859 				// display in MB
       
   860 				freeSpace = I64LOW(v.iFree / (1024 * 1024));
       
   861 				freeSpaceUnit = 'M';
       
   862 				}
       
   863 			else
       
   864 				{
       
   865 				// display in KB
       
   866 				freeSpace = I64LOW(v.iFree/1024);
       
   867 				freeSpaceUnit = 'K';
       
   868 				}
       
   869 			
       
   870 			if(v.iSize > KDiskUnitThreshold)
       
   871 				{
       
   872 				// display in MB
       
   873 				totalSpace = I64LOW(v.iSize / (1024 * 1024));
       
   874 				totalSpaceUnit = 'M';
       
   875 				}
       
   876 			else
       
   877 				{
       
   878 				// display in KB
       
   879 				totalSpace = I64LOW(v.iSize/1024);
       
   880 				totalSpaceUnit = 'K';
       
   881 				}
       
   882 			
       
   883 			test.Printf(_L("Free space on disk: %u %cB (of %u %cB)\r\n"), 
       
   884 						freeSpace, freeSpaceUnit, totalSpace, totalSpaceUnit);
       
   885 
       
   886             TTimeIntervalSeconds timeTaken;
       
   887             time.UniversalTime();            
       
   888             r=time.SecondsFrom(startTime,timeTaken);
       
   889             test(r==KErrNone);
       
   890             totalTime=timeTaken.Int();
       
   891 
       
   892             TInt seconds = totalTime % 60;
       
   893             TInt minutes = (totalTime / 60) % 60;
       
   894             TInt hours   = (totalTime / 3600) % 24;
       
   895             TInt days    = totalTime / (60 * 60 * 24);
       
   896             test.Printf(_L("Elapsed Time (%d): %d d %02d:%02d:%02d\r\n"), FillDiskCycle, days, hours, minutes, seconds);
       
   897             
       
   898             if(CurrentlyFillingDisk)
       
   899             	{
       
   900             	// work out ETA to full disk
       
   901 	            r = time.SecondsFrom(cycleTime, timeTaken);
       
   902     	        if((r == KErrNone) && (v.iSize > v.iFree))
       
   903     	        	{
       
   904 		            	totalTime = (TInt) ((v.iFree/1024 * (TInt64) timeTaken.Int()) / (v.iSize/1024 - v.iFree/1024));
       
   905 		    	        seconds = totalTime % 60;
       
   906     		    	    minutes = (totalTime / 60) % 60;
       
   907         		    	hours   = (totalTime / 3600) % 24;
       
   908 	            		days    = totalTime / (60 * 60 * 24);
       
   909             	
       
   910     	        		test.Printf(_L("ETA to full disk: %d d %02d:%02d:%02d\r\n"), days, hours, minutes, seconds);
       
   911         	    	}
       
   912             	}
       
   913             else 
       
   914             	{
       
   915             	// currently emptying disk, update time metrics
       
   916             	cycleTime.UniversalTime();
       
   917             	}            	
       
   918            	
       
   919 			}
       
   920 						
       
   921 			test.Printf(_L("\n"));
       
   922 		}
       
   923     }
       
   924 #endif
       
   925 
       
   926 
       
   927 GLDEF_C void CallTestsL()
       
   928 //
       
   929 // Call all tests
       
   930 //
       
   931     {
       
   932 	TInt r = TheFs.CharToDrive( gSessionPath[0], gDriveNumber );
       
   933 	test( KErrNone == r );
       
   934 	
       
   935 	// select appropriate metrics table
       
   936 	if(IsFileSystemFAT32(TheFs, gDriveNumber)) 
       
   937 		{
       
   938 		TheMetrics = &FAT32Metrics;
       
   939 		RDebug::Printf("Using FAT32 metrics\r\n");
       
   940 		}
       
   941 	else if(IsTestingLFFS())
       
   942 		{
       
   943 		TheMetrics = &LffsMetrics;
       
   944 		RDebug::Printf("Using LFFS metrics\r\n");
       
   945 		}
       
   946 	else
       
   947 		{
       
   948 		TDriveInfo driveInfo;
       
   949 		r=TheFs.Drive(driveInfo, gDriveNumber);
       
   950 		test(r==KErrNone);
       
   951 		
       
   952 		if((driveInfo.iType==EMediaNANDFlash) && !(driveInfo.iMediaAtt & KMediaAttWriteProtected))
       
   953 			{
       
   954 			TheMetrics = &NandMetrics;
       
   955 			RDebug::Printf("Using NAND metrics\r\n");
       
   956 			}
       
   957 		else 
       
   958 			{
       
   959 			TheMetrics = &DefMetrics;
       
   960 			RDebug::Printf("Using default metrics\r\n");
       
   961 			}
       
   962 		}
       
   963 		
       
   964 	FillDiskCycle = 1;
       
   965 #ifdef REUSE_THREAD
       
   966 	gRequestEnd = EFalse;
       
   967 #endif
       
   968 	DoTests();
       
   969 
       
   970     }
       
   971