First public contribution.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 //! @file f32test\concur\t_csfsoak.cpp
26 #include "t_cfssoak.h"
27 #include "f32_test_utils.h"
29 using namespace F32_Test_Utils;
34 GLDEF_D RTest test(_L("T_CFSTEST"));
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;
43 _LIT(KFsFile, "CFAFSDLY");
44 _LIT(KFsName, "DelayFS");
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;
51 LOCAL_D TInt KSessionWaitSlow = 50 * KTenthS;
53 LOCAL_D TBuf8<KBufLen> gBuff[KNumBuf];
54 LOCAL_D TRequestStatus gStat[KNumBuf];
56 LOCAL_D TChar gRemFsChr = 0;
57 LOCAL_D TInt gRemFsDrv = 0;
59 LOCAL_D TChar gDrvCh0 = 0;
60 LOCAL_D TChar gDrvCh1 = 0;
61 LOCAL_D TChar gDrvCh2 = 0;
63 LOCAL_D TInt gWaitTime = KSessionWaitSlow;
65 GLDEF_D TExtension gPrimaryExtensions[KMaxDrives];
67 inline void TraceError(const char* aFile, TInt aLine, const TDesC& aStr, TInt aRsp)
69 // 'Helper' routine to output the file and line of an error as well as a string
70 // and a response value.
74 TPtrC8 fptr((const TUint8*)aFile);
76 RDebug::Print(_L("%S:%d %S: r = %d"), &fbuf, aLine, &aStr, aRsp);
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)
83 LOCAL_C TChar MountTestFileSystem(TInt aDrive)
85 /// Mount a new CTestFileSystem on the drive under test.
86 /// @param aDrive Drive number (EDriveC etc.) to be used.
93 r=TheFs.DriveToChar(aDrive,c);
94 TESTLIT(r, "DriveToChar", r==KErrNone);
96 b.Format(_L("Mount test file system on %c:"),(TUint)c);
99 r=TheFs.AddFileSystem(KFsFile);
100 TESTLIT(r, "AddFileSystem", r==KErrNone || r==KErrAlreadyExists);
102 r=TheFs.FileSystemName(gOldFsName,aDrive);
103 TESTLIT(r, "FileSystemName", r==KErrNone || r==KErrNotFound);
106 r = TheFs.Drive(drv, gRemFsDrv);
107 TESTLIT(r, "Drive()", r == KErrNone);
109 gNoMedia = (drv.iType == EMediaUnknown || drv.iType == EMediaNotPresent);
111 if (gOldFsName.Length() > 0)
113 r = TheFs.ExtensionName(gPrimaryExtensions[aDrive].iName, aDrive, 0);
115 gPrimaryExtensions[aDrive].iExists = ETrue;
117 TTest::Printf(_L("Dismount %C: %S"), (TUint)c, &gOldFsName);
118 r=TheFs.DismountFileSystem(gOldFsName,aDrive);
119 TESTLIT(r, "DismountFileSystem", r==KErrNone);
122 if (gPrimaryExtensions[aDrive].iExists == EFalse)
123 r=TheFs.MountFileSystem(KFsName,aDrive);
125 r=TheFs.MountFileSystem(KFsName,gPrimaryExtensions[aDrive].iName,aDrive);
127 TESTLIT(r, "MountFileSystem", r==KErrNone);
129 r=TheFs.FileSystemName(gNewFsName,aDrive);
130 TESTLIT(r, "FileSystemName", r==KErrNone);
132 r = gNewFsName.CompareF(KFsName);
133 TESTLIT(r, "gNewFsName.Compare", r==0);
138 LOCAL_C void UnmountFileSystem(TInt aDrive)
140 /// Dismount the filesystem and remount the original one.
141 /// @param aDrive Drive number (EDriveC etc.) to be unmounted.
145 TInt r=TheFs.DriveToChar(aDrive,c);
146 TESTLIT(r, "DriveToChar", r==KErrNone);
148 if (gNewFsName.Length() > 0)
150 TTest::Printf(_L("Dismount %C: %S"), (TUint)c, &gNewFsName);
151 r=TheFs.DismountFileSystem(gNewFsName,aDrive);
152 TESTLIT(r, "DismountFileSystem", r==KErrNone);
154 // if there's no media present, don't try to mount it
157 TTest::Printf(_L("No media on %C: so don't remount it"), (TUint)c);
159 else if (gOldFsName.Length() > 0)
161 TTest::Printf(_L("Mount %C: %S"), (TUint)c, &gOldFsName);
162 if (gPrimaryExtensions[aDrive].iExists == EFalse)
163 r=TheFs.MountFileSystem(gOldFsName,aDrive);
165 r=TheFs.MountFileSystem(gOldFsName,gPrimaryExtensions[aDrive].iName,aDrive);
166 TESTLIT(r, "MountFileSystem", r==KErrNone);
171 LOCAL_C TInt TestCalibrate(TChar aDrvCh)
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).
181 TBool fast = (aDrvCh != gRemFsChr);
187 name.Format(_L("%C:\\cfstest.txt"), (TUint)aDrvCh);
189 r=fs.CharToDrive(aDrvCh, drive);
190 TESTLIT(r, "CharToDrive", r==KErrNone);
193 r = fs.Volume(info, drive);
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);
202 TInt64 bufSize64 = info.iFree / KNumBuf;
203 buffsize = bufSize64 > KBufLen ? KBufLen : I64LOW(bufSize64);
210 TTest::Printf(_L("Writing %d buffers of size %d"), KNumBuf, buffsize);
214 for (i = 0; i < KNumBuf; i++)
215 gBuff[i].Fill('*', fast ? buffsize : 100);
217 r = file.Replace(fs, name, EFileStreamText | EFileWrite);
219 TTest::Fail(HERE, r, _L("opening %S for writing"), name.Ptr());
223 TTimeIntervalMicroSeconds timeTaken;
224 startTime.HomeTime();
227 for (i = 0; i < KNumBuf; i++)
229 r = file.Write(gBuff[i]);
232 TTest::Printf(_L("Error writing file, r %d buffsize %d"), r, buffsize);
243 timeTaken=endTime.MicroSecondsFrom(startTime);
245 TInt64 dtime = timeTaken.Int64();
246 gWaitTime = I64LOW(dtime);
248 if (gWaitTime < KTenthS)
250 TTest::Printf(_L("Time to complete writes (%d uS) too short"), gWaitTime);
254 while (gWaitTime > 50*KSecond && buffsize > 100)
260 for (i = 0; i < KNumBuf; i++)
261 gBuff[i].Fill('*', buffsize);
263 TTest::Printf(_L("Time to complete writes %d mS"), gWaitTime / 1000);
268 void PrintBufStatus()
270 for (TInt i = 0; i < KNumBuf; i++)
272 TTest::Printf(_L("Req %d r %08X\n"), i, gStat[i].Int());
276 LOCAL_C TInt TestClose(TChar aDrvCh, TBool aCloseFs)
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.
282 /// @return KErrGeneral if an error was detected, KErrNone otherwise
294 r=TheFs.CharToDrive(aDrvCh, drive);
295 TESTLIT(r, "CharToDrive", r==KErrNone);
297 r=fs.FileSystemName(fsname, drive);
298 TESTLIT(r, "FileSystemName", r==KErrNone);
300 name.Format(_L("%C:\\cfstest.txt"), (TUint)aDrvCh);
301 TTest::Printf(_L("Testing %S (%S)"), &name, &fsname);
303 r = file.Replace(fs, name, EFileStreamText | EFileWrite);
305 TTest::Fail(HERE, r, _L("opening %S for writing"), name.Ptr());
308 for (i = 0; i < KNumBuf; i++)
310 file.Write(gBuff[i], gStat[i]);
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)
322 TTest::Printf(_L("Waiting %d mS"), waitTime / 1000);
323 User::After(waitTime);
326 TTest::Printf(_L("Wait ended"));
329 TTest::Printf(_L("Closing file server session"));
335 TTest::Printf(_L("Closing file"));
339 // test what has happened
344 TRequestStatus tstat;
347 timer.After(tstat, 2 * gWaitTime);
348 TInt requestsCompleted = 0;
349 for (i = 0; i < KNumBuf; i++)
351 User::WaitForRequest(tstat, gStat[i]);
353 if (tstat != KRequestPending)
355 TTest::Printf(_L("Timer expired"));
362 TTest::Printf(_L("write %d finished\n"), i);
368 TTest::Fail(HERE, _L("nCancelled > 0"));
372 TTest::Printf(_L("write %d cancelled\n"), i);
374 #if !defined(__WINS__) // under some loads the calibration is wrong by now and no writes have finished yet
379 TTest::Fail(HERE, _L("nFinished == 0"));
383 case KRequestPending:
384 TTest::Printf(_L("write %d pending\n"), i);
390 TTest::Fail(HERE, _L("nCancelled > 0"));
392 #if !defined(__WINS__) // timing issue as above
397 TTest::Fail(HERE, _L("nFinished == 0"));
402 TTest::Fail(HERE, r, _L("incorrect status for write %d"), i);
412 TTest::Printf(_L("write %d finished\n"), i);
418 TTest::Fail(HERE, _L("nCancelled > 0"));
422 TTest::Printf(_L("write %d cancelled\n"), i);
424 #if !defined(__WINS__) // under some loads the calibration is wrong by now and no writes have finished yet
429 TTest::Fail(HERE, _L("nFinished == 0"));
433 case KRequestPending:
434 TTest::Printf(_L("write %d pending\n"), i);
440 TTest::Fail(HERE, _L("nCancelled > 0"));
442 #if !defined(__WINS__) // timing issue as above
447 TTest::Fail(HERE, _L("nFinished == 0"));
452 TTest::Fail(HERE, r, _L("incorrect status for write %d"), i);
459 // If we HAVEN'T closed the file server session, we must wait for all the remaining
460 // requests, including the timer.
462 TTest::Printf(_L("Waiting for %d uncompleted requests\n"), KNumBuf + 1 - requestsCompleted);
463 for (i = requestsCompleted ; i < KNumBuf + 1 ; ++i)
464 User::WaitForAnyRequest();
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.
473 TTest::Printf(_L("Waiting for timer to complete\n"));
474 User::WaitForRequest(tstat);
482 r = fs.Entry(name, entry);
484 TTest::Fail(HERE, r, _L("Entry(%S)"), &name);
486 TInt nWritten = entry.iSize / gBuff[0].Length();
487 TTest::Printf(_L("Created file %d bytes, %d complete buffers written"),
488 entry.iSize, nWritten);
496 // At present, undefined whether cancelled or left pending
497 // TTest::Fail(HERE, _L("Not enough buffers (%d) cancelled"), nCancelled);
502 // At present, undefined whether cancelled or left pending
503 // TTest::Fail(HERE, _L("Too many buffers (%d) still pending"), nPending);
506 // Get the TFileCacheFlags for this drive
507 TVolumeInfo volInfo; // volume info for current drive
508 r = TheFs.Volume(volInfo, drive);
510 test.Printf(_L("DriveCacheFlags = %08X\n"), volInfo.iFileCacheFlags);
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)
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"));
522 #if !defined(__WINS__) // timing issue as above
525 TTest::Fail(HERE, _L("Not enough buffers (%d) written"), nFinished);
528 if (nWritten < nFinished)
530 TTest::Fail(HERE, _L("Only %d buffers written, should be %d"), nWritten, nFinished);
535 TTest::Printf(_L("Test %c: FAILED\n"), name[0]);
537 TTest::Printf(_L("Test %c: OK\n"), name[0]);
539 return (bad ? KErrGeneral : KErrNone);
542 LOCAL_C TInt TestCloseOperation()
544 /// Task to exercise the remote (special) filesystem.
547 TSoakRemote rem(gDrvCh1);
551 test.Next(_L("Mount as synchronous"));
553 r = TestCalibrate(gDrvCh1);
556 test.Next(_L("Test SubSession synchronous"));
557 r = TestClose(gDrvCh1, EFalse);
560 test.Next(_L("Test Session synchronous"));
561 r = TestClose(gDrvCh1, ETrue);
566 test.Next(_L("Mount as asynchronous"));
568 r = TestCalibrate(gDrvCh1);
571 test.Next(_L("Test SubSession asynchronous"));
572 r = TestClose(gDrvCh1, EFalse);
575 test.Next(_L("Test Session asynchronous"));
576 r = TestClose(gDrvCh1, ETrue);
581 return (ok ? KErrNone : KErrGeneral);
584 LOCAL_C TInt parseCmd(TInt aArgC, TPtrC aArgV[], TChar& dr0, TChar& dr1, TChar& dr2)
586 /// Get drive characters from the command line.
590 dr0 = User::UpperCase(aArgV[1][0]);
592 dr1 = User::UpperCase(aArgV[2][0]);
594 dr2 = User::UpperCase(aArgV[3][0]);
596 if (dr1 < 'A' || dr1 > 'Z')
602 GLDEF_C void CallTestsL()
607 //-- set up console output
608 F32_Test_Utils::SetConsole(test.Console());
610 for (TInt i = 0; i < KMaxDrives; i++)
612 gPrimaryExtensions[i].iExists = EFalse;
616 // first thing, initialise local test class to make sure it gets done.
617 TInt r = TTest::Init();
620 const TInt KMaxArgs = 4;
621 TPtrC argv[KMaxArgs];
622 TInt argc = TTest::ParseCommandArguments(argv, KMaxArgs);
624 gDrvCh0 = TTest::DefaultDriveChar();
626 r = parseCmd(argc, argv, gDrvCh0, gDrvCh1, gDrvCh2);
629 User::Exit(KErrAbort);
633 r = TheFs.CharToDrive(gRemFsChr, gRemFsDrv);
637 PrintDrvInfo(TheFs, gRemFsDrv);
639 if (r != KErrNone || gRemFsDrv == EDriveZ)
641 test.Printf(_L("Test cannnot run on drive %C:\n"), (TUint)gRemFsChr);
646 r = TheFs.Drive(drv, gRemFsDrv);
649 if(Is_Automounter(TheFs, gRemFsDrv))
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"));
657 // if it's a RAM drive or no media present, use the slow FS
658 if (drv.iType == EMediaRam)
660 test.Printf(_L("Test can't run on RAM drive %C:\n"), (TUint)gRemFsChr);
663 if (drv.iType == EMediaUnknown || drv.iType == EMediaNotPresent)
665 // Mount test filesystem on that drive
666 test.Printf(_L("Using slow filesystem on drive %C:\n"), (TUint)gRemFsChr);
667 MountTestFileSystem(gRemFsDrv);
671 // two parameters, mount the test filesystem on the first
672 MountTestFileSystem(gRemFsDrv);
676 // Use the existing filesystem on the drive
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);
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)"
689 r = TestCloseOperation();
691 // restore the original mounted drive if anything changed
692 UnmountFileSystem(gRemFsDrv);