kerneltest/f32test/concur/t_cfssimple.cpp
changeset 9 96e5fb8b040d
child 6 0173bcd7697c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/concur/t_cfssimple.cpp	Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,504 @@
+// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32test\concur\t_cfssimple.cpp
+// 
+//
+#define __E32TEST_EXTENSION__
+#include <f32file.h>
+#include <e32test.h>
+#include "t_server.h"
+#include "t_tdebug.h"
+
+GLDEF_D RTest test(_L("T_CFSSIMPLE"));
+GLDEF_D	RFs TheFs;
+
+LOCAL_D TFullName OldFsName;
+LOCAL_D TFileName NewFsName;
+
+_LIT(KFsFile, "CFAFSDLY");
+_LIT(KFsName, "DelayFS");
+
+
+struct TExtension
+	{
+	TFullName iName;
+	TBool iExists;
+	};
+
+LOCAL_D TExtension gPrimaryExtensions[KMaxDrives];
+
+LOCAL_C TChar MountTestFileSystem(TInt aDrive)
+//
+// Mount a new test filesystem on the drive under test
+//
+	{
+	TBuf<64> b;
+	TChar c;
+	TInt r;
+	if (aDrive > EDriveZ)
+		{
+		c = aDrive;
+		r=TheFs.CharToDrive(c, aDrive);
+		test_KErrNone(r);
+		}
+	else
+		{
+		r=TheFs.DriveToChar(aDrive,c);
+		test_KErrNone(r);
+		}
+
+	b.Format(_L("Test mounting of test file system on %c:"),(TUint)c);
+	test.Next(b);
+
+	test.Printf(_L("Load filesystem from %S\n"), &KFsFile);
+
+	r=TheFs.AddFileSystem(KFsFile);
+	test_Value(r, r == KErrNone || r == KErrAlreadyExists);
+	
+	r=TheFs.FileSystemName(OldFsName,aDrive);
+	test_Value(r, r == KErrNone || r == KErrNotFound);
+
+	if (OldFsName.Length() > 0)
+		{
+		r = TheFs.ExtensionName(gPrimaryExtensions[aDrive].iName, aDrive, 0);
+		if (r == KErrNone)
+			gPrimaryExtensions[aDrive].iExists = ETrue;
+
+		test.Printf(_L("Dismount %S filesystem on %c:\n"), &OldFsName, (TUint)c);
+		r=TheFs.DismountFileSystem(OldFsName,aDrive);
+		if (r == KErrNotReady)
+			{
+			TDriveInfo d;
+			r=TheFs.Drive(d, aDrive);
+			test_KErrNone(r);
+			if (d.iType == EMediaNotPresent)
+				test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)c);
+			else
+				test.Printf(_L("medium found (type %d) but drive %c: not ready\nPrevious test may have hung; else, check hardware.\n"), (TInt)d.iType, (TUint)c);
+			}
+		else if (r == KErrCorrupt)
+			test.Printf(_L("drive %c: corrupted, cannot unmount\nPrevious test may have aborted; else, check hardware.\n"), (TUint)c);
+
+		test_KErrNone(r);
+		}
+	
+	test.Printf(_L("Mount filesystem %S\n"), &KFsName);
+
+	if (gPrimaryExtensions[aDrive].iExists == EFalse)
+		r=TheFs.MountFileSystem(KFsName,aDrive);
+	else
+		r=TheFs.MountFileSystem(KFsName,gPrimaryExtensions[aDrive].iName,aDrive);
+	test_KErrNone(r);
+
+	r=TheFs.FileSystemName(NewFsName,aDrive);
+	test_KErrNone(r);
+	test(NewFsName.Compare(KFsName)==0);
+	test.Printf(_L("New %S filesystem on %c:\n"), &NewFsName, (TUint)c);
+
+	// Check attributes
+	TDriveInfo info;
+	r=TheFs.Drive(info,aDrive);
+	test_KErrNone(r);
+ 
+	test.Printf(_L("iType=%d,iBattery=%d,iDriveAtt=%x,iMediaAtt=%x\n"),(TUint)info.iType,\
+		(TUint)info.iBattery,info.iDriveAtt,info.iMediaAtt);
+	return c;
+	}
+
+LOCAL_C void UnmountFileSystem(TInt aDrive)
+//
+// Unmount the test filesystem on the drive under test
+//
+	{
+	TChar c;
+	TInt r;
+	if (aDrive > EDriveZ)
+		{
+		c = aDrive;
+		r=TheFs.CharToDrive(c, aDrive);
+		test_KErrNone(r);
+		}
+	else
+		{
+		r=TheFs.DriveToChar(aDrive,c);
+		test_KErrNone(r);
+		}
+    test.Printf(_L("Dismount %S filesystem on %c\n"), &NewFsName, (TUint)c);
+	r=TheFs.DismountFileSystem(NewFsName,aDrive);
+	test_KErrNone(r);
+	if (OldFsName.Length() > 0)
+		{
+		test.Printf(_L("Remount %S filesystem on %c\n"), &OldFsName, (TUint)c);
+
+		if (gPrimaryExtensions[aDrive].iExists == EFalse)
+			r=TheFs.MountFileSystem(OldFsName,aDrive);
+		else
+			r=TheFs.MountFileSystem(OldFsName,gPrimaryExtensions[aDrive].iName,aDrive);
+		test_KErrNone(r);
+		}
+	}
+
+template <TInt N>
+LOCAL_C TDes* cvtbuff(const TDesC8& buff, TBuf<N>& b)
+//
+// Copy an 8-bit buffer to a character one.
+//
+	{
+	TInt i;
+	TInt len = buff.Length();
+	TInt max = b.MaxLength();
+	if (len > max)
+		len = max;
+	b.SetLength(len);
+	for (i = 0; i < len; i++)
+		b[i] = TText(buff[i]);
+	return &b;
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID FSBASE-CR-PCHY-6PALT2
+//! @SYMTestType CT
+//! @SYMREQ CR PCHY-6PALT2
+//! @SYMTestCaseDesc Test asynchronous RFs::Flush(TRequestStatus& aStatus)
+//! @SYMTestStatus Implemented
+//! @SYMTestActions Perform an asynchronous flush and wait for completion
+//! @SYMTestExpectedResults Asynchronous flush completes after expected delay
+//! @SYMTestPriority Low
+//! @SYMAuthor Stefan Williams
+//! @SYMCreationDate 01/06/2006
+//! @See EFSRV and EFILE components
+//! @file f32test\concur\t_cfssimple.cpp
+//---------------------------------------------
+
+LOCAL_C void testAsyncFlush(RFile& aFile)
+    {
+ 	TTest::Printf(_L("Test Async RFile::Flush()"));
+
+	RTimer flushTimer;
+	TRequestStatus flushTimerStatus;
+	TInt err = flushTimer.CreateLocal();
+    TEST(err == KErrNone);
+
+	flushTimer.After(flushTimerStatus, 10000000); // 10 seconds timeout for RFile::Flush on CFAFSDLY file system
+
+	TTime startFlush;
+	startFlush.HomeTime();
+
+	TRequestStatus flushStatus;
+	aFile.Flush(flushStatus);
+    TEST(flushStatus==KRequestPending);
+
+	User::WaitForRequest(flushTimerStatus, flushStatus);
+	if ((flushStatus == KRequestPending) && (flushTimerStatus == KErrNone))
+		{
+		TTest::Fail(HERE, _L("Flush : Timed Out"));
+		}
+
+	if (flushStatus != KErrNone)
+		{
+		TTest::Fail(HERE, flushStatus.Int(), _L("Flush : Error"));
+		}
+
+	TTime endFlush;
+	endFlush.HomeTime();
+
+    TTimeIntervalSeconds flushTime;
+    err = endFlush.SecondsFrom(startFlush, flushTime);
+    TEST(err == KErrNone);
+
+	TTest::Printf(_L("Flush took %d seconds"), flushTime.Int());
+
+	if(flushTime.Int() < 3)
+		{
+		TTest::Fail(HERE, _L("Flush took < 3 Seconds"));
+		}
+
+	flushTimer.Cancel();
+	flushTimer.Close();
+	}
+
+LOCAL_C TInt testAccessFile(TAny*)
+//
+// Test read file handling with two threads.
+//
+    {
+	TTest::Start(_L("Test write file"));
+	
+	TThreadData& data = TTest::Self();
+	TFileName fileName = data.iFile;
+
+	TTest::Printf(_L("Connect to myFs\n"));
+
+	RFs   myFs;
+	TInt r = myFs.Connect();
+	TEST(r==KErrNone);
+
+	TTest::Printf(_L("Create %S\n"), &fileName);
+
+    RFile f;
+
+    r = f.Replace(myFs, fileName, EFileStreamText | EFileWrite);
+    TEST(r==KErrNone);
+
+	// wait for both tasks to have a chance to complete opening the files
+	User::After(1000);
+
+	const TInt KNumBuf = 10;
+	const TInt KBufLen = 0x80;
+    TBuf8<KBufLen> a[KNumBuf];
+    TBuf8<KBufLen> b;
+	TBuf<KBufLen>  tbuf;
+	TInt i;
+
+	TUint base = 0;
+	for (i = 0; i < fileName.Length(); i++)
+		base = base * 0x11 + fileName[i];
+	base += base / 32;
+	base = base % 32 + 0x30;
+
+	TRequestStatus status[10];
+
+	TTest::Next(_L("Write file"));
+    for (i = 0; i <= 9; i++)
+        {
+		TChar val = TChar(base + i);
+		a[i].Fill(TText(val), i+1);
+		TTest::Printf(_L("write '%S' started\n"), cvtbuff(a[i], tbuf));
+        f.Write(a[i], status[i]);
+		User::After(1);
+		if (r != KErrNone)
+			{
+			TTest::Fail(HERE, r, _L("Write"));
+			}
+        }
+
+	for (i = 0; i < 10; i++)
+		{
+		User::WaitForAnyRequest();
+		if (status[i] == KRequestPending)
+			{
+			TTest::Printf(_L("write %d still pending!\n"), i);
+			}
+		else
+			{
+			TTest::Printf(_L("write %d completed with status %d\n"), i, status[i].Int());
+			}
+		}
+
+	TTest::Printf(_L("Write 64 bytes at the end as padding\n"));
+	TBuf8<32> fill;
+	fill.Fill(TText('_'), 32);
+	f.Write(fill);
+	f.Write(fill);
+
+	testAsyncFlush(f);
+
+    f.Close();
+
+	b.Fill(TText('*'), b.MaxLength());
+	TTest::Next(_L("Read file"));
+
+	// wait to allow the dust to settle
+	User::After(1000000);
+	
+    r = f.Open(myFs, fileName, EFileStreamText);
+    TEST(r==KErrNone);
+
+	for (i = 0; i < 10; i++)
+        {
+         r=f.Read(b, 12-i);
+		if (r == KErrNone)
+			{
+			TTest::Printf(_L("read %2d bytes <%S>\n"), b.Length(), cvtbuff(b, tbuf));
+			}
+		else
+			{
+			TTest::Fail(HERE, r, _L("Read"));
+			}
+		User::After(1);
+        }
+    r=f.Read(b);
+	if (r != KErrNone)
+		{
+		TTest::Fail(HERE, r, _L("Read\n"));
+		// TEST(r==KErrNone);
+		}
+    if (!(b.Length()==0))
+		{
+		cvtbuff(b, tbuf);
+		TTest::Printf(_L("read %2d bytes <%.32S>\n"), b.Length(), &tbuf);
+		}
+
+	// wait to allow the dust to settle
+	User::After(1000000);
+	
+	TTest::Printf(_L("Close file"));
+    f.Close();
+
+	TTest::Printf(_L("Close session"));
+	myFs.Close();
+	return r;
+    }
+
+LOCAL_C TInt createThread(TThreadFunction aFunc, TChar aDrvCh)
+//
+// Create a thread using function aFunc on drive aDrvCh
+//
+	{
+	static TInt tnum = 0;
+	TBuf<2>  drive(_L("?"));
+	TBuf<64> name;
+    drive[0] = TText(aDrvCh);
+	drive.UpperCase();
+	TThreadData& d = TTest::Data(tnum);
+	d.iFile.Format(_L("%S:\\TEST%d.FILE"), &drive, tnum);
+	name.Format(_L("Test_%S_%d"), &drive, tnum);
+	TInt r = TTest::Create(tnum, aFunc, name);
+	++tnum;
+	return r;
+	}
+
+LOCAL_C TInt testThreads(TChar aDrvCh1, TChar aDrvCh2)
+//
+// Create threads operating on files on two drives.
+//
+	{
+	TInt r;
+	r = createThread(testAccessFile, aDrvCh1);
+	r = createThread(testAccessFile, aDrvCh2);
+	r = TTest::Run();
+	return r;
+	}
+
+LOCAL_C TBool isSpace(TChar c)
+//
+// Return true if the character is space or tab
+//
+	{
+	return (c == ' ' || c == '\t');
+	}
+
+LOCAL_C void parseCmd(TDesC& cmd, TChar& dr0, TChar& dr1, TChar& dr2)
+// 
+// Parse command line to get two characters for drive 1 and 2
+//
+	{
+	TInt i = 0;
+	TInt n = cmd.Length();
+	// skip to first non-space
+	while (i < n && isSpace(cmd[i]))
+		++i;
+	if (i < n)
+		dr0 = cmd[i];
+	// skip to first space
+	while (i < n && !isSpace(cmd[i]))
+		++i;
+	// skip to first non-space
+	while (i < n && isSpace(cmd[i]))
+		++i;
+	if (i < n)
+		dr1 = cmd[i];
+	// skip to first space
+	while (i < n && !isSpace(cmd[i]))
+		++i;
+	// skip to first non-space
+	while (i < n && isSpace(cmd[i]))
+		++i;
+	if (i < n)
+		dr2 = cmd[i];
+	// skip to first space
+	while (i < n && !isSpace(cmd[i]))
+		++i;
+	}
+
+GLDEF_C void CallTestsL()
+//
+// Do all tests
+//
+	{
+	TBuf<0x100> cmd;
+	User::CommandLine(cmd);
+	cmd.UpperCase();
+
+	TChar dr0 = 'F';
+	TChar dr1 = 0;
+	TChar dr2 = 0;
+	parseCmd(cmd, dr0, dr1, dr2);
+
+	if (dr1 < 'A')
+		dr1 = dr0;
+	
+	if (dr2 < 'A')
+		dr2 = dr1;
+	
+	if (dr0 < 'A' || dr0 >= 'Z')
+		{
+		test.Printf(_L("Test cannnot run on drive\n"));
+		return;
+		}
+
+	MountTestFileSystem(dr0);
+	// TheFs.SetVolumeLabel(_L("TRACE"));
+	TInt r = testThreads(dr1, dr2);
+	TheFs.SetVolumeLabel(_L("OFF"));
+	UnmountFileSystem(dr0);
+	test_KErrNone(r);
+	}
+
+GLDEF_C TInt E32Main()
+//
+// Main entry point
+//
+    {
+
+	for (TInt i = 0; i < KMaxDrives; i++)
+		{
+		gPrimaryExtensions[i].iExists = EFalse;
+		}
+
+    TInt r;
+    CTrapCleanup* cleanup;
+    cleanup=CTrapCleanup::New();
+    __UHEAP_MARK;
+
+    test.Title();
+    test.Start(_L("Starting tests..."));
+
+    r=TheFs.Connect();
+    test_KErrNone(r);
+
+    // TheFs.SetAllocFailure(gAllocFailOn);
+    TTime timerC;
+    timerC.HomeTime();
+
+    TRAP(r,CallTestsL());
+
+    // reset the debug register
+    TheFs.SetDebugRegister(0);
+
+    TTime endTimeC;
+    endTimeC.HomeTime();
+    TTimeIntervalSeconds timeTakenC;
+    r=endTimeC.SecondsFrom(timerC,timeTakenC);
+    test_KErrNone(r);
+    test.Printf(_L("Time taken for test = %d seconds\n"),timeTakenC.Int());
+    // TheFs.SetAllocFailure(gAllocFailOff);
+    TheFs.Close();
+    test.End();
+    test.Close();
+    __UHEAP_MARKEND;
+    delete cleanup;
+    return(KErrNone);
+    }
+