os/kernelhwsrv/kerneltest/f32test/filesystem/fat/t_checkdisk.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_CHECKDISK.cpp
    15 //
    16 //
    17 #define __E32TEST_EXTENSION__
    18 #include <f32file.h>
    19 #include <e32test.h>
    20 //#include <e32svr.h>
    21 //#include <f32dbg.h>
    22 #include "t_server.h"
    23 //#include <e32twin.h>
    24 
    25 RTest test(_L("T_CHECKDISK"));
    26 
    27 RFs TheFs;
    28 TInt gDrive;
    29 TFileName gSessionPath;
    30 TChar gDriveToTest;
    31 
    32 
    33 HBufC8* gBuf = NULL;
    34 TPtr8 gBufReadPtr(NULL, 0);
    35 HBufC8* gBufSec = NULL;
    36 TPtr8 gBufWritePtr(NULL, 0);
    37 
    38 const TInt KOneK = 1024;
    39 const TInt KOneMeg = KOneK * 1024;
    40 const TInt KBlockSize = KOneK * 129 ;
    41 const TInt KWaitRequestsTableSize = 70;
    42 
    43 TInt gBigFileSize = 0;
    44 TInt gSmallFileSize = 0;
    45 TInt64 gMediaSize = 0;
    46 TBool gSkip=EFalse;
    47 TInt writeSize = KBlockSize;
    48 TInt seekSize = 0;
    49 TSeek seekType = ESeekAddress;
    50 TInt reduceSize = 0;
    51 
    52 TTimeIntervalMicroSeconds32 gTimeTakenBigFile(0);
    53 TBuf16<45> gSmallFile, gBigFile;
    54 LOCAL_D TInt gNextFile=0;
    55 TTime gTime1;
    56 TTime gTime2;
    57 
    58 LOCAL_D RSemaphore gSync;
    59 
    60 // Concurrent Threads
    61 RThread gBig;
    62 RThread gSmall;
    63 LOCAL_D RSemaphore client;
    64 LOCAL_D const TInt KHeapSize=0x4000;
    65 LOCAL_D const TInt KMaxHeapSize=0x100000;
    66 TRequestStatus gStatus[KWaitRequestsTableSize];
    67 
    68 enum TTestState
    69 	{
    70 	EThreadWait,
    71 	EThreadSignal,
    72 	ENoThreads
    73 	};
    74 
    75 //
    76 // Generates a name of the form FFFFF*<aPos>.TXT (aLong.3)
    77 //
    78 GLDEF_C void FileNameGen(TDes16& aBuffer, TInt aLong, TInt aPos)
    79 	{
    80 	TInt padding;
    81 	TInt i=0;
    82 	TBuf16<10> tempbuf;
    83 
    84 	_LIT(KNumber,"%d");
    85 	tempbuf.Format(KNumber,aPos);
    86 	padding=aLong-tempbuf.Size()/2;
    87 	aBuffer=_L("");
    88 	while(i<padding)
    89 		{
    90 		aBuffer.Append('F');
    91 		i++;
    92 		}
    93 	aBuffer.Append(tempbuf);
    94 
    95 	_LIT(KExtension1, ".TXT");
    96 	aBuffer.Append(KExtension1);
    97 	}
    98 
    99 
   100 
   101 
   102 //
   103 // Expects a drive letter as a parameter
   104 //
   105 LOCAL_C void parseCommandLine()
   106 	{
   107 	TBuf<0x100> cmd;
   108 	User::CommandLine(cmd);
   109 	TLex lex(cmd);
   110 	TPtrC token=lex.NextToken();
   111 	TInt r=0;
   112 
   113 	if(token.Length()!=0)
   114 		{
   115 		gDriveToTest=token[0];
   116 		gDriveToTest.UpperCase();
   117 		}
   118 	else
   119 		{
   120 		gDriveToTest='C';
   121 		}
   122 
   123 		r=TheFs.CharToDrive(gDriveToTest,gDrive);
   124 		test_KErrNone(r);
   125 		gSessionPath=_L("?:\\F32-TST\\");
   126 		gSessionPath[0]=(TText)gDriveToTest;
   127 		test.Printf(_L("\nCLP=%S\n"),&token);
   128 	}
   129 
   130 //
   131 // Fills a buffer with character aC
   132 //
   133 LOCAL_C void FillBuffer(TDes8& aBuffer, TInt aLength, TChar aC)
   134 	{
   135 	test (aBuffer.MaxLength() >= aLength);
   136 	for(TInt i=0; i<aLength; i++)
   137 		{
   138 		aBuffer.Append(aC);
   139 		}
   140 	}
   141 
   142 //
   143 // Waits for all the TRequestStatus in status[] to complete
   144 //
   145 LOCAL_C void WaitForAll(TRequestStatus status[], TInt aSize)
   146 	{
   147 	TInt i=0;
   148 
   149 	while(i<aSize)
   150 		{
   151 		User::WaitForRequest(status[i++]);
   152 		}
   153 	}
   154 
   155 
   156 //
   157 // Writes a file synchronously in blocks of aBlockSize size
   158 // this function can be called from another thread, therefore requires its own RTest instance
   159 LOCAL_C TInt WriteFile(RFs& fs, TDes16& aFile, TInt aSize, TInt aBlockSize, TTestState aState)
   160 	{
   161 	RTest test(_L(""));
   162 
   163 	TInt r=0;
   164 	RFile fileWrite;
   165 
   166 	test(aBlockSize>0);				// Block size must be greater than 0
   167 
   168 	if(aState==EThreadWait)
   169 		{
   170 		gSync.Wait();
   171 		}
   172 	r=fileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite);
   173 	test_KErrNone(r);
   174 
   175 	TInt j=0;
   176 	while(j<aSize)
   177 		{
   178 		r=fileWrite.Write(gBufWritePtr, writeSize);
   179 		test_KErrNone(r);
   180 		if(seekType)
   181 			{
   182 			r=fileWrite.Seek(seekType, seekSize);
   183 			test_KErrNone(r);
   184 
   185 			if (writeSize + reduceSize >= 0)
   186 				writeSize += reduceSize;
   187 
   188 			writeSize = Min(writeSize, gBufWritePtr.Length());
   189 
   190 			}
   191 		if((j==0)&&(aState==EThreadSignal))
   192 			{
   193 			gSync.Signal();
   194 			}
   195 		j+=aBlockSize;
   196 		}
   197 
   198 	fileWrite.Close();
   199 
   200 	return KErrNone;
   201 	}
   202 
   203 LOCAL_C void IniStatus(TRequestStatus aStatus[], TInt aSize)
   204 	{
   205 	TInt i=0;
   206 
   207 	while(i<aSize)
   208 		{
   209 		aStatus[i++]=KRequestPending;
   210 		}
   211 	}
   212 
   213 //
   214 // Write big file
   215 // This is a thread function, therefore requires its own RTest instance
   216 LOCAL_C TInt WriteBigFile(TAny* )
   217 	{
   218 	RTest test(_L(""));
   219 	RFs fs;
   220 	TInt r=fs.Connect(gDriveToTest);
   221 	test_KErrNone(r);
   222 
   223 	r=fs.SetSessionPath(gSessionPath);
   224 	test_KErrNone(r);
   225 
   226 	WriteFile(fs, gBigFile, gBigFileSize, KBlockSize, EThreadSignal);
   227 	gTime1.HomeTime();
   228 
   229 	client.Signal();
   230 	return ETrue;
   231 	}
   232 
   233 //
   234 // Writes a file asynchronously in blocks of aBlockSize size
   235 // this function can be called from another thread, therefore requires its own RTest instance
   236 LOCAL_C void WriteFileAsync(RFs& fs, RFile& aFileWrite, TDes16& aFile, TInt aSize, TInt aBlockSize, TRequestStatus aStatus[])
   237 	{
   238 	RTest test(_L(""));
   239 
   240 	TInt r=0;
   241 
   242 	test(aBlockSize>0);				// Block size must be greater than 0
   243 	test((aSize%aBlockSize)==0); 	// Ensure the size of the file is a multiple of the block size
   244 
   245 	r=aFileWrite.Replace(fs,aFile,EFileShareAny|EFileWrite);
   246 	test_KErrNone(r);
   247 
   248 	TInt j=0,i=0;
   249 	while(j<aSize)
   250 		{
   251 		aFileWrite.Write(gBufWritePtr,aStatus[i++]);
   252 		j+=aBlockSize;
   253 		}
   254 	}
   255 
   256 
   257 
   258 //
   259 // Write big file async
   260 // This is a thread function, therefore requires its own RTest instance
   261 LOCAL_C TInt WriteBigFileAsync(TAny* )
   262 	{
   263 	RTest test(_L(""));
   264 	RFs fs;
   265 	TInt r=fs.Connect(gDriveToTest);
   266 	test_KErrNone(r);
   267 
   268 	r=fs.SetSessionPath(gSessionPath);
   269 	test_KErrNone(r);
   270 
   271 
   272 	RFile bigFile;
   273 
   274 	IniStatus(gStatus,KWaitRequestsTableSize);
   275 	WriteFileAsync(fs, bigFile, gSmallFile, gBigFileSize, KBlockSize,gStatus);
   276 	gSync.Signal();
   277 	WaitForAll(gStatus, gBigFileSize/KBlockSize);
   278 
   279 	return ETrue;
   280 	}
   281 
   282 static void TestClientDies()
   283 	{
   284 	test.Next(_L("Client dying unexpectedly"));
   285 
   286 	TInt r=0;
   287 	TBuf<20> unit=_L("?:\\");
   288 	unit[0]=(TText)gDriveToTest;
   289 
   290 	//-------------------------------------------
   291 	test.Printf(_L("Sync test\n"));
   292 
   293 	r=gBig.Create(_L("TEST1"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   294 	test_KErrNone(r);
   295 
   296 	gBig.Resume();
   297 	gSync.Wait();
   298 
   299 	gBig.Kill(-2);
   300 	gBig.Close();
   301 	User::After(500000);
   302 
   303 	r=TheFs.CheckDisk(unit);
   304 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   305 
   306 	//-------------------------------------------
   307 	test.Printf(_L("Async test\n"));
   308 	r=gSmall.Create(_L("TEST2"),WriteBigFileAsync,KDefaultStackSize*2,KHeapSize,KMaxHeapSize,NULL);
   309 	test_KErrNone(r);
   310 
   311 	gSmall.Resume();
   312 	gSync.Wait();
   313 
   314 	gSmall.Kill(-2);
   315 	gSmall.Close();
   316 	User::After(500000);
   317 
   318 	r=TheFs.CheckDisk(unit);
   319 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   320 
   321 	//-------------------------------------------
   322 	test.Printf(_L("Testing for size not multiple of blocksize\n"));
   323 
   324 	writeSize = 5000;
   325 	r=gBig.Create(_L("TEST3"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   326 	test_KErrNone(r);
   327 	gBig.Resume();
   328 	gSync.Wait();
   329 
   330 	gBig.Kill(-2);
   331 	gBig.Close();
   332 	User::After(500000);
   333 
   334 	r=TheFs.CheckDisk(unit);
   335 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   336 
   337 	//-------------------------------------------
   338 	test.Printf(_L("Testing with seek current and write inside the file boundary\n"));
   339 
   340 	writeSize = 5000;
   341 	seekType = ESeekCurrent;
   342 	seekSize = -5000;
   343 	reduceSize = -3000;
   344 	r=gBig.Create(_L("TEST4"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   345 	test_KErrNone(r);
   346 	gBig.Resume();
   347 	gSync.Wait();
   348 
   349 	gBig.Kill(-2);
   350 	gBig.Close();
   351 	User::After(500000);
   352 
   353 	r=TheFs.CheckDisk(unit);
   354 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   355 
   356 	//-------------------------------------------
   357 	test.Printf(_L("Testing with seek current and overwrite entire file\n"));
   358 	writeSize = 5000;
   359 	seekType = ESeekCurrent;
   360 	seekSize = -5000;
   361 	reduceSize = 0;
   362 	r=gBig.Create(_L("TEST5"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   363 	test_KErrNone(r);
   364 	gBig.Resume();
   365 	gSync.Wait();
   366 
   367 	gBig.Kill(-2);
   368 	gBig.Close();
   369 	User::After(500000);
   370 
   371 	r=TheFs.CheckDisk(unit);
   372 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   373 
   374 	//-------------------------------------------
   375 	test.Printf(_L("Testing with seek current and write outside the file boundary\n"));
   376 
   377 	writeSize = 5000;
   378 	seekType = ESeekCurrent;
   379 	seekSize = -5000;
   380 	reduceSize = 5000;
   381 	r=gBig.Create(_L("TEST6"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   382 	test_KErrNone(r);
   383 	gBig.Resume();
   384 	gSync.Wait();
   385 
   386 	gBig.Kill(-2);
   387 	gBig.Close();
   388 	User::After(500000);
   389 
   390 	r=TheFs.CheckDisk(unit);
   391 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   392 
   393 	//-------------------------------------------
   394 	test.Printf(_L("Testing with seek current and write within the file boundary\n"));
   395 	writeSize = 5000;
   396 	seekType = ESeekCurrent;
   397 	seekSize = -3000;
   398 	reduceSize = -4000;
   399 	r=gBig.Create(_L("TEST7"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   400 	test_KErrNone(r);
   401 	gBig.Resume();
   402 	gSync.Wait();
   403 
   404 	gBig.Kill(-2);
   405 	gBig.Close();
   406 	User::After(500000);
   407 
   408 	r=TheFs.CheckDisk(unit);
   409 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   410 
   411 	//-------------------------------------------
   412 	test.Printf(_L("Testing with seek current and write exactly to file size\n"));
   413 	writeSize = 5000;
   414 	seekType = ESeekCurrent;
   415 	seekSize = -3000;
   416 	reduceSize = -3000;
   417 	r=gBig.Create(_L("TEST8"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   418 	test_KErrNone(r);
   419 	gBig.Resume();
   420 	gSync.Wait();
   421 
   422 	gBig.Kill(-2);
   423 	gBig.Close();
   424 	User::After(500000);
   425 
   426 	r=TheFs.CheckDisk(unit);
   427 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   428 
   429 	//-------------------------------------------
   430 	test.Printf(_L("Testing with seek current and write greater than file size\n"));
   431 	writeSize = 5000;
   432 	seekType = ESeekCurrent;
   433 	seekSize = -3000;
   434 	reduceSize = 10000;
   435 	r=gBig.Create(_L("TEST9"),WriteBigFile,KDefaultStackSize,KHeapSize,KMaxHeapSize,NULL);
   436 	test_KErrNone(r);
   437 	gBig.Resume();
   438 	gSync.Wait();
   439 
   440 	gBig.Kill(-2);
   441 	gBig.Close();
   442 	User::After(500000);
   443 
   444 	r=TheFs.CheckDisk(unit);
   445 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   446 
   447 	TInt retries = 0;
   448 
   449 	do
   450 		{
   451 		r=TheFs.ScanDrive(unit);
   452 		if (r != KErrNone)
   453 			test.Printf(_L("ScanDrive() returned %d\n"), r);
   454 		if (r == KErrInUse)
   455 			User::After(500000);
   456 		}
   457 	while (r == KErrInUse && ++retries < 5);
   458 
   459 	test_Value(r, r == KErrNone || r == KErrNotSupported);
   460 
   461 	}
   462 
   463 
   464 //---------------------------------------------------------------------
   465 /**
   466     Test that CheckDisk will not cause stack overflow on very deep directory structure.
   467 */
   468 void TestCheckDisk_VeryDeepDirectory()
   469 	{
   470 	test.Next(_L("Testing deep dir structure check"));
   471 
   472 	TInt nRes;
   473 	TBuf<20> unit=_L("?:\\");
   474 	unit[0]=(TText)gDriveToTest;
   475 
   476 	//-- 1. create deep dir structure, like \\0\\1\\2\\...... 90 levels deep
   477 	const TInt KMaxDirDepth = 90;
   478 
   479 	test.Printf(_L("Creating directory with %d subdirs.\n"),KMaxDirDepth);
   480 
   481 	TFileName fn;
   482 	for(TInt i=0; i<KMaxDirDepth; ++i)
   483 		{
   484 		fn.AppendFormat(_L("\\%d"), i%10);
   485 		}
   486 	fn.Append(_L("\\"));
   487 
   488 	nRes = TheFs.MkDirAll(fn);
   489 	test_Value(nRes, nRes == KErrNone || nRes == KErrAlreadyExists);
   490 
   491 	//-- 2. invoke Check Disk and ensure that target doesn't die from stack overflow.
   492 	test.Printf(_L("Running Check Disk...\n"));
   493 	nRes = TheFs.CheckDisk(unit);
   494 
   495 	test_Value(nRes, nRes == KErrNone || nRes == KErrTooBig);
   496 	}
   497 
   498 
   499 //---------------------------------------------------------------------
   500 //
   501 // This test tries to read a small file while writing a big one
   502 //
   503 GLDEF_C void CallTestsL()
   504 	{
   505 	TBuf16<45> dir;
   506 
   507 	test.Next(_L("Preparing the environmnet\n"));
   508 
   509 	FileNameGen(gSmallFile, 8, gNextFile++);
   510 	FileNameGen(gBigFile, 8, gNextFile++);
   511 	dir=gSessionPath;
   512 	dir.Append(gSmallFile);
   513 	gSmallFile=dir;
   514 	dir=gSessionPath;
   515 	dir.Append(gBigFile);
   516 	gBigFile=dir;
   517 
   518 	TRAPD(res,gBuf = HBufC8::NewL(KBlockSize+1));
   519 	test(res == KErrNone && gBuf != NULL);
   520 
   521 	gBufWritePtr.Set(gBuf->Des());
   522 	FillBuffer(gBufWritePtr, KBlockSize, 'B');
   523 
   524 	TRAPD(res2,gBufSec = HBufC8::NewL(KBlockSize+1));
   525 	test(res2 == KErrNone && gBufSec != NULL);
   526 	gBufReadPtr.Set(gBufSec->Des());
   527 
   528 	//---------------------------
   529 
   530 	TestClientDies();
   531 	TestCheckDisk_VeryDeepDirectory();
   532 
   533 	delete gBuf;
   534 	delete gBufSec;
   535 	}
   536 
   537 LOCAL_C void DoTests()
   538 	{
   539  	TInt r=0;
   540 
   541  	r=client.CreateLocal(0);
   542 	test_KErrNone(r);
   543 
   544   	r=gSync.CreateLocal(0);
   545 	test_KErrNone(r);
   546 
   547 	r=TheFs.SetSessionPath(gSessionPath);
   548 	test_KErrNone(r);
   549 
   550 	r=TheFs.MkDirAll(gSessionPath);
   551 	test_Value(r, r == KErrNone || r == KErrAlreadyExists);
   552 
   553 	TheFs.ResourceCountMarkStart();
   554 	TRAP(r,CallTestsL());
   555 	test_KErrNone(r);
   556 	TheFs.ResourceCountMarkEnd();
   557 	}
   558 
   559 TBool CheckForDiskSize()
   560 	{
   561 	TVolumeInfo volInfo;
   562 	TInt r = TheFs.Volume(volInfo, gDrive);
   563 	test_KErrNone(r);
   564 
   565 	gMediaSize = volInfo.iSize;
   566 	gSmallFileSize = KBlockSize;
   567 	gBigFileSize = KBlockSize*20;
   568 	while(((2*gBigFileSize)+KOneMeg) > gMediaSize )
   569 		{
   570 			gBigFileSize -= (2*KBlockSize);
   571 		}
   572 
   573 	if(gBigFileSize< (3*gSmallFileSize))
   574 		return EFalse;
   575 	else
   576 		return ETrue;
   577 	}
   578 
   579 void Format(TInt aDrive)
   580 	{
   581 
   582 	test.Next(_L("Format"));
   583 	TBuf<4> driveBuf=_L("?:\\");
   584 	driveBuf[0]=(TText)(aDrive+'A');
   585 	RFormat format;
   586 	TInt count;
   587 	TInt r=format.Open(TheFs,driveBuf,EQuickFormat,count);
   588 	test_KErrNone(r);
   589 
   590 	while(count)
   591 		{
   592 		TInt r=format.Next(count);
   593 		test_KErrNone(r);
   594 		}
   595 	format.Close();
   596 	}
   597 
   598 
   599 static TBool IsFAT(RFs &aFsSession, TInt aDrive)
   600 {
   601 	_LIT(KFatName, "Fat");
   602 
   603 	TFileName f;
   604 	TInt r = aFsSession.FileSystemName(f, aDrive);
   605 	test_Value(r, r == KErrNone || r == KErrNotFound);
   606 	return (f.CompareF(KFatName) == 0);
   607 }
   608 
   609 
   610 GLDEF_C TInt E32Main()
   611 	{
   612 
   613 	CTrapCleanup* cleanup;
   614 	cleanup=CTrapCleanup::New();
   615 
   616 	__UHEAP_MARK;
   617 	test.Title();
   618 	test.Start(_L("Starting tests..."));
   619 	parseCommandLine();
   620 
   621 	TInt r = TheFs.Connect();
   622 	test_KErrNone(r);
   623 
   624 	TDriveInfo info;
   625 	TVolumeInfo volInfo;
   626 	r=TheFs.Drive(info,gDrive);
   627 	test_KErrNone(r);
   628 
   629 	if(info.iMediaAtt&KMediaAttVariableSize)
   630 		{// Not testing in RAM Drives
   631 		test.Printf(_L("Tests skipped in RAM drive\n"));
   632 		goto out;
   633         }
   634 
   635 	r = TheFs.Volume(volInfo, gDrive);
   636 	if (r == KErrNotReady)
   637 		{
   638 		if (info.iType == EMediaNotPresent)
   639 			test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)gDriveToTest);
   640 		else
   641 			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);
   642 		}
   643 	else if (r == KErrCorrupt)
   644 		{
   645 		test.Printf(_L("%c: Media corruption; previous test may have aborted; else, check hardware\n"), (TUint)gDriveToTest);
   646 		}
   647 	test_KErrNone(r);
   648 
   649 	if(!IsFAT(TheFs, gDrive))
   650         {
   651 		test.Printf(_L("Tests skipped on non-FAT drive\n"));
   652 		goto out;
   653         }
   654 
   655 	if ((volInfo.iDrive.iMediaAtt & KMediaAttFormattable))
   656 		Format(gDrive);
   657 
   658 	if(CheckForDiskSize())
   659 		{
   660 		DoTests();
   661 		if ((volInfo.iDrive.iMediaAtt & KMediaAttFormattable))
   662 		   Format(gDrive);
   663 		}
   664 	else
   665 		{
   666 		test.Printf(_L("Skipping tests due to lack of space to perform them in this unit\n"));
   667 		}
   668 out:
   669 	test.End();
   670 
   671 	TheFs.Close();
   672 	test.Close();
   673 
   674 	__UHEAP_MARKEND;
   675 	delete cleanup;
   676 	return(KErrNone);
   677     }