os/kernelhwsrv/kerneltest/f32test/concur/t_cfstest.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-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 //
    15 
    16 //! @file f32test\concur\t_csfsoak.cpp
    17 
    18 #include <f32file.h>
    19 #include <e32test.h>
    20 #include <e32math.h>
    21 #include <f32dbg.h>
    22 
    23 #include "t_server.h"
    24 #include "t_chlffs.h"
    25 #include "t_tdebug.h"
    26 #include "t_cfssoak.h"
    27 #include "f32_test_utils.h"
    28 
    29 using namespace F32_Test_Utils;
    30 
    31 
    32 
    33 
    34 GLDEF_D RTest test(_L("T_CFSTEST"));
    35 
    36 LOCAL_D TFullName gFsName;
    37 LOCAL_D TFullName gFsName1;
    38 LOCAL_D TFullName gFsName2;
    39 LOCAL_D TFullName gOldFsName;
    40 LOCAL_D TFullName gNewFsName;
    41 LOCAL_D TBool     gNoMedia = ETrue;
    42 
    43 _LIT(KFsFile,   "CFAFSDLY");
    44 _LIT(KFsName,   "DelayFS");
    45 
    46 LOCAL_D const TInt32 KSecond = 1000000;
    47 LOCAL_D const TInt32 KTenthS = KSecond/10;
    48 LOCAL_D const TInt   KNumBuf = 10;
    49 LOCAL_D const TInt   KBufLen = 50000;
    50 
    51 LOCAL_D TInt KSessionWaitSlow = 50 * KTenthS;
    52 
    53 LOCAL_D TBuf8<KBufLen> gBuff[KNumBuf];
    54 LOCAL_D TRequestStatus gStat[KNumBuf];
    55 
    56 LOCAL_D TChar gRemFsChr = 0;
    57 LOCAL_D TInt  gRemFsDrv = 0;
    58 
    59 LOCAL_D TChar gDrvCh0 = 0;
    60 LOCAL_D TChar gDrvCh1 = 0;
    61 LOCAL_D TChar gDrvCh2 = 0;
    62 
    63 LOCAL_D	TInt  gWaitTime = KSessionWaitSlow;
    64 
    65 GLDEF_D TExtension gPrimaryExtensions[KMaxDrives];
    66 
    67 inline void TraceError(const char* aFile, TInt aLine, const TDesC& aStr, TInt aRsp)
    68 //
    69 // 'Helper' routine to output the file and line of an error as well as a string
    70 // and a response value.
    71 //
    72     {
    73     TBuf<256> fbuf;
    74     TPtrC8    fptr((const TUint8*)aFile);
    75     fbuf.Copy(fptr);
    76     RDebug::Print(_L("%S:%d  %S: r = %d"), &fbuf, aLine, &aStr, aRsp);
    77     }
    78 
    79 #define TESTSTR(r,s,cond) if (!(cond)) { TraceError(__FILE__, __LINE__, (s), (r)); test(0); }
    80 #define TESTLIT(r,s,cond) { _LIT(KStr,s); TESTSTR(r,KStr,cond); }
    81 #define TESTRES(r,cond)   TESTLIT(r,"ERROR",cond)
    82 
    83 LOCAL_C TChar MountTestFileSystem(TInt aDrive)
    84 ///
    85 /// Mount a new CTestFileSystem on the drive under test.
    86 /// @param aDrive Drive number (EDriveC etc.) to be used.
    87 ///
    88 	{
    89 	TInt r;
    90 	// Check attributes
    91 	TBuf<64> b;
    92 	TChar c;
    93 	r=TheFs.DriveToChar(aDrive,c);
    94 	TESTLIT(r, "DriveToChar", r==KErrNone);
    95 
    96 	b.Format(_L("Mount test file system on %c:"),(TUint)c);
    97 	test.Next(b);
    98 
    99 	r=TheFs.AddFileSystem(KFsFile);
   100 	TESTLIT(r, "AddFileSystem", r==KErrNone || r==KErrAlreadyExists);
   101 
   102 	r=TheFs.FileSystemName(gOldFsName,aDrive);
   103 	TESTLIT(r, "FileSystemName", r==KErrNone || r==KErrNotFound);
   104 
   105 	TDriveInfo drv;
   106 	r = TheFs.Drive(drv, gRemFsDrv);
   107 	TESTLIT(r, "Drive()", r == KErrNone);
   108 
   109 	gNoMedia = (drv.iType == EMediaUnknown || drv.iType == EMediaNotPresent);
   110 
   111 	if (gOldFsName.Length() > 0)
   112 		{
   113 		r = TheFs.ExtensionName(gPrimaryExtensions[aDrive].iName, aDrive, 0);
   114 		if (r == KErrNone)
   115 			gPrimaryExtensions[aDrive].iExists = ETrue;
   116 
   117 		TTest::Printf(_L("Dismount %C: %S"), (TUint)c, &gOldFsName);
   118 		r=TheFs.DismountFileSystem(gOldFsName,aDrive);
   119 		TESTLIT(r, "DismountFileSystem", r==KErrNone);
   120 		}
   121 	
   122 	if (gPrimaryExtensions[aDrive].iExists == EFalse)
   123 		r=TheFs.MountFileSystem(KFsName,aDrive);
   124 	else
   125 		r=TheFs.MountFileSystem(KFsName,gPrimaryExtensions[aDrive].iName,aDrive);
   126 
   127 	TESTLIT(r, "MountFileSystem", r==KErrNone);
   128 
   129 	r=TheFs.FileSystemName(gNewFsName,aDrive);
   130 	TESTLIT(r, "FileSystemName", r==KErrNone);
   131 		
   132 	r = gNewFsName.CompareF(KFsName);
   133 	TESTLIT(r, "gNewFsName.Compare", r==0);
   134 		
   135 	return c;
   136 	}
   137 
   138 LOCAL_C void UnmountFileSystem(TInt aDrive)
   139 ///
   140 /// Dismount the filesystem and remount the original one.
   141 /// @param aDrive Drive number (EDriveC etc.) to be unmounted.
   142 ///
   143 	{
   144 	TChar c;
   145 	TInt r=TheFs.DriveToChar(aDrive,c);
   146 	TESTLIT(r, "DriveToChar", r==KErrNone);
   147 
   148 	if (gNewFsName.Length() > 0)
   149 		{
   150 		TTest::Printf(_L("Dismount %C: %S"), (TUint)c, &gNewFsName);
   151 		r=TheFs.DismountFileSystem(gNewFsName,aDrive);
   152 		TESTLIT(r, "DismountFileSystem", r==KErrNone);
   153 
   154 		// if there's no media present, don't try to mount it
   155 		if (gNoMedia)
   156 			{
   157 			TTest::Printf(_L("No media on %C: so don't remount it"), (TUint)c);
   158 			}
   159 		else if (gOldFsName.Length() > 0)
   160 			{
   161 			TTest::Printf(_L("Mount    %C: %S"), (TUint)c, &gOldFsName);
   162 			if (gPrimaryExtensions[aDrive].iExists == EFalse)
   163 				r=TheFs.MountFileSystem(gOldFsName,aDrive);
   164 			else
   165 				r=TheFs.MountFileSystem(gOldFsName,gPrimaryExtensions[aDrive].iName,aDrive);
   166 			TESTLIT(r, "MountFileSystem", r==KErrNone);
   167 			}
   168 		}
   169 	}
   170 
   171 LOCAL_C TInt TestCalibrate(TChar aDrvCh)
   172 ///
   173 /// Calibrate the timing for writing the data buffers.  This also sets up
   174 /// the buffers to the appropriate length (fast file systems such as LFFS
   175 /// and FAT need big buffers, the slow test filesystem needs small ones).
   176 ///
   177     {
   178 	TFileName name;
   179 	RFile file;
   180 	RFs   fs;
   181 	TBool fast = (aDrvCh != gRemFsChr);
   182 	TInt  drive;
   183 	TInt  r;
   184 
   185 	fs.Connect();
   186 
   187 	name.Format(_L("%C:\\cfstest.txt"), (TUint)aDrvCh);
   188 
   189 	r=fs.CharToDrive(aDrvCh, drive);
   190 	TESTLIT(r, "CharToDrive", r==KErrNone);
   191 
   192 	TVolumeInfo info;
   193 	r = fs.Volume(info, drive);
   194 	if (r != KErrNone)
   195 		TTest::Fail(HERE, r, _L("Getting volume info"));
   196 	TTest::Printf(_L("Total space on drive %C = %ld (0x%lX)"), (TUint) aDrvCh, info.iSize, info.iSize);
   197 	TTest::Printf(_L("Free space on drive %C = %ld (0x%lX)"), (TUint) aDrvCh, info.iFree, info.iFree);
   198 	
   199 	TInt buffsize;
   200 	if (fast)
   201 		{
   202 		TInt64 bufSize64 = info.iFree / KNumBuf;
   203 		buffsize = bufSize64 > KBufLen ? KBufLen : I64LOW(bufSize64);
   204 		}
   205 	else
   206 		{
   207 		buffsize = 100;
   208 		}
   209 
   210 	TTest::Printf(_L("Writing %d buffers of size %d"), KNumBuf, buffsize);
   211 
   212 
   213     TInt i;
   214     for (i = 0; i < KNumBuf; i++)
   215 		gBuff[i].Fill('*', fast ? buffsize : 100);
   216 
   217     r = file.Replace(fs, name, EFileStreamText | EFileWrite);
   218     if (r != KErrNone)
   219         TTest::Fail(HERE, r, _L("opening %S for writing"), name.Ptr());
   220 
   221     TTime startTime;
   222     TTime endTime;
   223     TTimeIntervalMicroSeconds timeTaken;
   224     startTime.HomeTime();
   225 
   226 
   227     for (i = 0; i < KNumBuf; i++)
   228         {
   229         r = file.Write(gBuff[i]);
   230 		if (r != KErrNone)
   231 			{
   232 			TTest::Printf(_L("Error writing file, r %d buffsize %d"), r, buffsize);
   233 			file.Close();
   234 			fs.Close();
   235 			return r;
   236 			}
   237         }
   238 
   239 	file.Close();
   240 	fs.Close();
   241 
   242     endTime.HomeTime();
   243     timeTaken=endTime.MicroSecondsFrom(startTime);
   244 
   245     TInt64 dtime = timeTaken.Int64();
   246 	gWaitTime = I64LOW(dtime);
   247 
   248 	if (gWaitTime < KTenthS)
   249 		{
   250 		TTest::Printf(_L("Time to complete writes (%d uS) too short"), gWaitTime);
   251 		return KErrGeneral;
   252 		}
   253 
   254 	while (gWaitTime > 50*KSecond && buffsize > 100)
   255 		{
   256 		gWaitTime /= 10;
   257 		buffsize /= 10;
   258 		}
   259 
   260 	for (i = 0; i < KNumBuf; i++)
   261 		gBuff[i].Fill('*', buffsize);
   262 
   263 	TTest::Printf(_L("Time to complete writes %d mS"), gWaitTime / 1000);
   264 
   265 	return KErrNone;
   266 	}
   267 
   268 void PrintBufStatus()
   269 	{
   270     for (TInt i = 0; i < KNumBuf; i++)
   271 		{
   272 		TTest::Printf(_L("Req %d r %08X\n"), i, gStat[i].Int());
   273 		}
   274 	}
   275 
   276 LOCAL_C TInt TestClose(TChar aDrvCh, TBool aCloseFs)
   277 ///
   278 /// Test what happens when a file is closed in the middle of writing it.  Note
   279 /// that this assumes that the filesystem under test has been calibrated and
   280 /// the buffers set up already.
   281 ///
   282 /// @return KErrGeneral if an error was detected, KErrNone otherwise
   283 ///
   284     {
   285 	TFileName fsname;
   286 	TFileName name;
   287 	RFile file;
   288 	RFs   fs;
   289 	TInt  drive;
   290 	TInt  r;
   291 
   292 	fs.Connect();
   293 
   294 	r=TheFs.CharToDrive(aDrvCh, drive);
   295 	TESTLIT(r, "CharToDrive", r==KErrNone);
   296 
   297 	r=fs.FileSystemName(fsname, drive);
   298 	TESTLIT(r, "FileSystemName", r==KErrNone);
   299 
   300 	name.Format(_L("%C:\\cfstest.txt"), (TUint)aDrvCh);
   301 	TTest::Printf(_L("Testing %S (%S)"), &name, &fsname);
   302 
   303     r = file.Replace(fs, name, EFileStreamText | EFileWrite);
   304     if (r != KErrNone)
   305         TTest::Fail(HERE, r, _L("opening %S for writing"), name.Ptr());
   306 
   307     TInt i;
   308     for (i = 0; i < KNumBuf; i++)
   309         {
   310         file.Write(gBuff[i], gStat[i]);
   311         }
   312 
   313 	// wait for around a half of the writes to complete, then close the file
   314 	// before the others finish.
   315 	// If the media is unexpectedly slow and hasn't written a single buffer, wait a little bit longer
   316 	TInt KMaxWaitTime =  Max(gWaitTime * 3, KSessionWaitSlow);
   317 	TInt totalTimeWaited = 0;
   318 	for (TInt waitTime = gWaitTime/2; 
   319 		totalTimeWaited < KMaxWaitTime && gStat[0].Int() == KRequestPending;
   320 		totalTimeWaited+= waitTime, waitTime = gWaitTime / 10)
   321 		{
   322 		TTest::Printf(_L("Waiting %d mS"), waitTime / 1000);
   323 		User::After(waitTime);
   324 		}
   325 
   326     TTest::Printf(_L("Wait ended"));
   327 	if (aCloseFs)
   328 		{
   329 		TTest::Printf(_L("Closing file server session"));
   330 		fs.Close();
   331 		}
   332 		
   333 	else
   334 		{
   335 		TTest::Printf(_L("Closing file"));
   336 		file.Close();
   337 		}
   338 
   339     // test what has happened
   340 	TInt nFinished  = 0;
   341 	TInt nCancelled = 0;
   342 	TInt nPending   = 0;
   343     TBool bad = EFalse;
   344 	TRequestStatus tstat;
   345 	RTimer timer;
   346 	timer.CreateLocal();
   347 	timer.After(tstat, 2 * gWaitTime);
   348 	TInt requestsCompleted = 0;
   349     for (i = 0; i < KNumBuf; i++)
   350         {
   351         User::WaitForRequest(tstat, gStat[i]);
   352 		++requestsCompleted;
   353 		if (tstat != KRequestPending)
   354 			{
   355 			TTest::Printf(_L("Timer expired"));
   356 			break;
   357 			}
   358         r = gStat[i].Int();
   359         switch (r)
   360             {
   361             case KErrNone:
   362                 TTest::Printf(_L("write %d finished\n"), i);
   363 				nFinished++;
   364 				if (nCancelled > 0)
   365 					{
   366 					bad = ETrue;
   367 					PrintBufStatus();
   368 					TTest::Fail(HERE, _L("nCancelled > 0"));
   369 					}
   370                 break;
   371             case KErrCancel:
   372                 TTest::Printf(_L("write %d cancelled\n"), i);
   373 				nCancelled++;
   374 #if !defined(__WINS__) // under some loads the calibration is wrong by now and no writes have finished yet
   375 				if (nFinished == 0)
   376 					{
   377 					bad = ETrue;
   378 					PrintBufStatus();
   379 					TTest::Fail(HERE, _L("nFinished == 0"));
   380 					}
   381 #endif
   382                 break;
   383 			case KRequestPending:
   384                 TTest::Printf(_L("write %d pending\n"), i);
   385 				nPending++;
   386 				if (nCancelled > 0)
   387 					{
   388 					bad = ETrue;
   389 					PrintBufStatus();
   390 					TTest::Fail(HERE, _L("nCancelled > 0"));
   391 					}
   392 #if !defined(__WINS__) // timing issue as above
   393 				if (nFinished == 0)
   394 					{
   395 					bad = ETrue;
   396 					PrintBufStatus();
   397 					TTest::Fail(HERE, _L("nFinished == 0"));
   398 					}
   399 #endif
   400                 break;
   401             default:
   402 				TTest::Fail(HERE, r, _L("incorrect status for write %d"), i);
   403             }
   404         }
   405 
   406 	while (i < KNumBuf)
   407 		{
   408         r = gStat[i].Int();
   409         switch (r)
   410             {
   411             case KErrNone:
   412                 TTest::Printf(_L("write %d finished\n"), i);
   413 				nFinished++;
   414 				if (nCancelled > 0)
   415 					{
   416 					bad = ETrue;
   417 					PrintBufStatus();
   418 					TTest::Fail(HERE, _L("nCancelled > 0"));
   419 					}
   420                 break;
   421             case KErrCancel:
   422                 TTest::Printf(_L("write %d cancelled\n"), i);
   423 				nCancelled++;
   424 #if !defined(__WINS__) // under some loads the calibration is wrong by now and no writes have finished yet
   425 				if (nFinished == 0)
   426 					{
   427 					bad = ETrue;
   428 					PrintBufStatus();
   429 					TTest::Fail(HERE, _L("nFinished == 0"));
   430 					}
   431 #endif
   432                 break;
   433 			case KRequestPending:
   434                 TTest::Printf(_L("write %d pending\n"), i);
   435 				nPending++;
   436 				if (nCancelled > 0)
   437 					{
   438 					bad = ETrue;
   439 					PrintBufStatus();
   440 					TTest::Fail(HERE, _L("nCancelled > 0"));
   441 					}
   442 #if !defined(__WINS__) // timing issue as above
   443 				if (nFinished == 0)
   444 					{
   445 					bad = ETrue;
   446 					PrintBufStatus();
   447 					TTest::Fail(HERE, _L("nFinished == 0"));
   448 					}
   449 #endif
   450                 break;
   451             default:
   452 				TTest::Fail(HERE, r, _L("incorrect status for write %d"), i);
   453 			}
   454 		i++;
   455 		}
   456 
   457 	if (!aCloseFs)
   458 		{
   459 		// If we HAVEN'T closed the file server session, we must wait for all the remaining
   460 		// requests, including the timer.
   461 		
   462 		TTest::Printf(_L("Waiting for %d uncompleted requests\n"), KNumBuf + 1 - requestsCompleted);
   463 		for (i = requestsCompleted ; i < KNumBuf + 1 ; ++i)
   464 			User::WaitForAnyRequest();
   465 		}
   466 	else
   467 		{
   468 		// If we have closed the session, then we need to work out if the timer went off (by
   469 		// checking if there are any writes still pending) and if not then we need to wait for it.
   470 		
   471 		if (nPending == 0)
   472 			{
   473 			TTest::Printf(_L("Waiting for timer to complete\n"));
   474 			User::WaitForRequest(tstat);
   475 			}
   476 		}
   477 
   478 	if (aCloseFs)
   479 		fs.Connect();
   480 
   481 	TEntry entry;
   482 	r = fs.Entry(name, entry);
   483 	if (r != KErrNone)
   484 		TTest::Fail(HERE, r, _L("Entry(%S)"), &name);
   485 
   486 	TInt nWritten = entry.iSize / gBuff[0].Length();
   487 	TTest::Printf(_L("Created file %d bytes, %d complete buffers written"),
   488 				  entry.iSize, nWritten);
   489 	
   490     fs.Delete(name);
   491 
   492 	fs.Close();
   493 
   494 	if (nCancelled < 2)
   495 		{
   496 		// At present, undefined whether cancelled or left pending
   497 		// TTest::Fail(HERE, _L("Not enough buffers (%d) cancelled"), nCancelled);
   498 		}
   499 
   500 	if (nPending > 0)
   501 		{
   502 		// At present, undefined whether cancelled or left pending
   503 		// TTest::Fail(HERE, _L("Too many buffers (%d) still pending"), nPending);
   504 		}
   505 
   506 	// Get the TFileCacheFlags for this drive
   507 	TVolumeInfo volInfo;	// volume info for current drive
   508 	r = TheFs.Volume(volInfo, drive);
   509 	test(r==KErrNone);
   510 	test.Printf(_L("DriveCacheFlags = %08X\n"), volInfo.iFileCacheFlags);
   511 
   512 	// There's no point testing the numbers of buffers written if write caching enabled, as
   513 	// in this case, the write requests are completed successfully before the data is written to disk
   514 	if ((volInfo.iFileCacheFlags & EFileCacheWriteOn) && aCloseFs)
   515 		{
   516 		test.Printf(_L("%d write requests completed, %d of %d buffers written to disk\n"), nFinished, nWritten, KNumBuf);
   517 		test.Printf(_L("Skipping test for buffers written as write caching enabled and FS session destroyed\n"));
   518 		}
   519 	else
   520 		{
   521 
   522 #if !defined(__WINS__) // timing issue as above
   523 		if (nWritten < 2)
   524 			{
   525 			TTest::Fail(HERE, _L("Not enough buffers (%d) written"), nFinished);
   526 			}
   527 #endif
   528 		if (nWritten < nFinished)
   529 			{
   530 			TTest::Fail(HERE, _L("Only %d buffers written, should be %d"), nWritten, nFinished);
   531 			}
   532 		}
   533 
   534     if (bad)
   535         TTest::Printf(_L("Test %c: FAILED\n"), name[0]);
   536     else
   537         TTest::Printf(_L("Test %c: OK\n"), name[0]);
   538 	
   539     return (bad ? KErrGeneral : KErrNone);
   540     }
   541 
   542 LOCAL_C TInt TestCloseOperation()
   543 ///
   544 /// Task to exercise the remote (special) filesystem.
   545 ///
   546 	{
   547 	TSoakRemote rem(gDrvCh1);
   548 	TInt r = KErrNone;
   549 	TBool ok = ETrue;
   550 
   551 	test.Next(_L("Mount as synchronous"));
   552 	rem.Remount(ETrue);
   553 	r = TestCalibrate(gDrvCh1);
   554 	if (r == KErrNone)
   555 		{
   556 		test.Next(_L("Test SubSession synchronous"));
   557 		r = TestClose(gDrvCh1, EFalse);
   558 		if (r != KErrNone)
   559 			ok = EFalse;
   560 		test.Next(_L("Test Session synchronous"));
   561 		r = TestClose(gDrvCh1, ETrue);
   562 		if (r != KErrNone)
   563 			ok = EFalse;
   564 		}
   565 
   566 	test.Next(_L("Mount as asynchronous"));
   567 	rem.Remount(EFalse);
   568 	r = TestCalibrate(gDrvCh1);
   569 	if (r == KErrNone)
   570 		{
   571 		test.Next(_L("Test SubSession asynchronous"));
   572 		r = TestClose(gDrvCh1, EFalse);
   573 		if (r != KErrNone)
   574 			ok = EFalse;
   575 		test.Next(_L("Test Session asynchronous"));
   576 		r = TestClose(gDrvCh1, ETrue);
   577 		if (r != KErrNone)
   578 			ok = EFalse;
   579 		}
   580 
   581 	return (ok ? KErrNone : KErrGeneral);
   582 	}
   583 
   584 LOCAL_C TInt parseCmd(TInt aArgC, TPtrC aArgV[], TChar& dr0, TChar& dr1, TChar& dr2)
   585 ///
   586 /// Get drive characters from the command line.
   587 ///
   588     {
   589 	if (aArgC > 1)
   590 		dr0 = User::UpperCase(aArgV[1][0]);
   591 	if (aArgC > 2)
   592 		dr1 = User::UpperCase(aArgV[2][0]);
   593 	if (aArgC > 3)
   594 		dr2 = User::UpperCase(aArgV[3][0]);
   595 
   596     if (dr1 < 'A' || dr1 > 'Z')
   597 		dr1 = dr0;
   598 
   599     return KErrNone;
   600     }
   601 
   602 GLDEF_C void CallTestsL()
   603 ///
   604 /// Do all tests.
   605 ///
   606 	{
   607     //-- set up console output 
   608     F32_Test_Utils::SetConsole(test.Console()); 
   609 
   610 	for (TInt i = 0; i < KMaxDrives; i++)
   611 		{
   612 		gPrimaryExtensions[i].iExists = EFalse;
   613 		}
   614 
   615 
   616 	// first thing, initialise local test class to make sure it gets done.
   617 	TInt r = TTest::Init();
   618 	test(r == KErrNone);
   619 	
   620 	const TInt KMaxArgs = 4;
   621 	TPtrC argv[KMaxArgs];
   622 	TInt  argc = TTest::ParseCommandArguments(argv, KMaxArgs);
   623 
   624 	gDrvCh0 = TTest::DefaultDriveChar();
   625 
   626 	r = parseCmd(argc, argv, gDrvCh0, gDrvCh1, gDrvCh2);
   627 	if (r != KErrNone)
   628 		{
   629 		User::Exit(KErrAbort);
   630 		}
   631 
   632 	gRemFsChr = gDrvCh0;
   633 	r = TheFs.CharToDrive(gRemFsChr, gRemFsDrv);
   634 
   635     test(r == KErrNone);
   636     
   637     PrintDrvInfo(TheFs, gRemFsDrv);
   638 
   639 	if (r != KErrNone || gRemFsDrv == EDriveZ)
   640 		{
   641 		test.Printf(_L("Test cannnot run on drive %C:\n"), (TUint)gRemFsChr);
   642 		return;
   643 		}
   644 
   645 	TDriveInfo drv;
   646 	r = TheFs.Drive(drv, gRemFsDrv);
   647 	test(r == KErrNone);
   648 
   649     if(Is_Automounter(TheFs, gRemFsDrv))
   650     {
   651 		//-- this test tries to mount the curent drive as a synchronous one, 
   652         //-- automounter can't work on synchronous drives.
   653         test.Printf(_L("This test can't be performed on AutoMounter FS, Skipping.\n"));
   654 		return;
   655     }
   656 
   657 	// if it's a RAM drive or no media present, use the slow FS
   658 	if (drv.iType == EMediaRam)
   659 		{
   660 		test.Printf(_L("Test can't run on RAM drive %C:\n"), (TUint)gRemFsChr);
   661 		return;
   662 		}
   663 	if (drv.iType == EMediaUnknown || drv.iType == EMediaNotPresent)
   664 		{
   665 		// Mount test filesystem on that drive
   666 		test.Printf(_L("Using slow filesystem on drive %C:\n"), (TUint)gRemFsChr);
   667 		MountTestFileSystem(gRemFsDrv);
   668 		}
   669 	else if (argc > 2)
   670 		{
   671 		// two parameters, mount the test filesystem on the first
   672 		MountTestFileSystem(gRemFsDrv);
   673 		}
   674 	else
   675 		{
   676 		// Use the existing filesystem on the drive
   677 		gRemFsChr = 0;
   678 		}
   679 
   680 	// If we can do it, check whether the drive is LFFS and is OK
   681 // !!! Disable platform security tests until we get the new APIs
   682 //	if (User::Capability() & KCapabilityRoot)
   683 //		CheckMountLFFS(TheFs, gDrvCh1);
   684 
   685     //!!!!! Warning: MountTestFileSystem() and UnmountFileSystem() code is lousy! it always mounts back the drive as SYNCHRONOUS.
   686     //!!!!! anyway, this code seems not to be called, because of "else if (argc > 2)"
   687 
   688 	// Do tests
   689 	r = TestCloseOperation();
   690 
   691 	// restore the original mounted drive if anything changed
   692 	UnmountFileSystem(gRemFsDrv);
   693 
   694 	test(r == KErrNone);
   695 	}
   696 
   697