persistentstorage/store/TFILE/t_storfserr.cpp
changeset 0 08ec8eefde2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/store/TFILE/t_storfserr.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,436 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+//
+
+#include <s32file.h>
+#include <e32test.h>
+
+LOCAL_D RTest test(_L("t_storfserr"));
+
+#ifdef _DEBUG
+
+LOCAL_D CTrapCleanup* TheTrapCleanup = NULL;
+LOCAL_D RFs TheFs;
+
+const TInt KTestCleanupStack=0x20;
+const TPtrC KTestDir=_L("\\STOR-TST\\T_FSERR\\");
+const TPtrC FileNameA=_L("A.DAT");
+const TPtrC FileNameB=_L("B.DAT");
+
+const TPtrC des2(_S("22"),2);
+const TPtrC des3(_S("333"),3);
+const TPtrC des4(_S("4444"),4);
+const TPtrC des5(_S("55555"),5);
+LOCAL_D CFileStore* store = NULL;
+RStoreWriteStream out;
+RStoreReadStream in;
+
+LOCAL_C void setupCleanup()
+    {// Initialise the cleanup stack
+	TheTrapCleanup=CTrapCleanup::New();
+	test(TheTrapCleanup!=NULL);
+	TRAPD(r,\
+		{\
+		for (TInt i=KTestCleanupStack;i>0;i--)\
+			CleanupStack::PushL((TAny*)0);\
+		CleanupStack::Pop(KTestCleanupStack);\
+		});
+	test(r==KErrNone);
+	}
+
+LOCAL_C void setupTestDirectory()
+    {// Prepare the test directory.
+	TInt r=TheFs.MkDirAll(KTestDir);
+	test(r==KErrNone||r==KErrAlreadyExists);
+	r=TheFs.SetSessionPath(KTestDir);
+	test(r==KErrNone);
+	}
+
+LOCAL_D void AlterStoreL(TInt aFail)
+	{
+	RStoreWriteStream out2;
+	RStoreWriteStream out3;
+	RStoreWriteStream out4;
+	RStoreReadStream in;
+	TheFs.SetErrorCondition(KErrNotReady,aFail);
+	TStreamId id0 = out.CreateLC(*store);
+	out << _L("012345678901234567890123456789012345678901234567890123456789");
+	out.CommitL();
+	CleanupStack::PopAndDestroy();
+
+	TStreamId id2 = out.CreateLC(*store);
+	out.CommitL();
+	CleanupStack::PopAndDestroy();
+
+	TStreamId id3 = out.CreateLC(*store);
+	out.CommitL();
+	CleanupStack::PopAndDestroy();
+
+	TStreamId id4 = out.CreateLC(*store);
+	out << _L("mum");
+	out.CommitL();
+	CleanupStack::PopAndDestroy();
+
+	out.ReplaceLC(*store,store->Root());
+	out << id2;
+	out << id3;
+	out << id4;
+	out << KNullStreamId;
+	out << KNullStreamId;
+	out.CommitL();
+	CleanupStack::PopAndDestroy();
+
+	in.OpenLC(*store,store->Root());// use the root for in and out streams
+	out.ReplaceLC(*store,store->Root());
+	out.WriteL(in);
+	out.CommitL();
+	CleanupStack::PopAndDestroy(2);
+
+	out.ReplaceLC(*store,store->Root());// swap the order
+	in.OpenLC(*store,store->Root());
+	out.WriteL(in);
+	out << KNullStreamId;
+	out.CommitL();
+	CleanupStack::PopAndDestroy(2);
+
+	store->CommitL();
+
+	in.OpenLC(*store,store->Root());
+	TStreamId idX,idZ;
+	in >> idX;
+	in >> idX;
+	in >> idZ;// id4 "mum"
+	CleanupStack::PopAndDestroy();
+	out.OpenLC(*store,idZ);
+	in.OpenLC(*store,idZ);
+	out2.OpenLC(*store,idZ);
+	out3.OpenLC(*store,idZ);
+	out4.OpenLC(*store,idZ);
+	out4.WriteL(in);
+	out.CommitL();
+	CleanupStack::PopAndDestroy(5);
+
+	store->CompactL();
+	store->CommitL();
+
+	store->DeleteL(id0);
+	store->CommitL();
+
+	store->CompactL();
+	store->CommitL();
+	}
+
+enum TFileQoS
+	{
+	ESimple			= 0,//File, "write byte" is an atomic operation
+	EBlockAtomic	= 1,//File, "block write" is an atomic operation
+	ETransactional	= 2,//Transactional file system.
+	ELastQoSType
+	};
+
+const TInt KFailPoints[ELastQoSType][2] =
+	{
+	// non-transactional file system
+		{
+		5, 54
+		},
+	// atomic "block write"
+		{
+		3, 38
+		},
+	// transactional file system
+		{
+		3, 38
+		}
+	};
+
+//The function returns true, if the file system guarantees atomic "block write" operations on aDriveNo.
+TBool IsBlockAtomic(TInt aDriveNo)
+	{
+	__ASSERT_DEBUG(aDriveNo >= EDriveA && aDriveNo <= EDriveZ, User::Invariant());
+
+	TVolumeIOParamInfo volInfo;
+	TInt err = TheFs.VolumeIOParam(aDriveNo, volInfo);
+	//If VolumeIOParam() succeeds, the media block size is >= 512 bytes and the media block size is power of two - report
+	//that the media supports atomic "block write" operations.
+	const TInt KDefaultMediaBlockSize = 512;
+	return err == KErrNone && volInfo.iBlockSize >= KDefaultMediaBlockSize && (volInfo.iBlockSize & (volInfo.iBlockSize - 1)) == 0;
+	}
+
+TFileQoS MediaType(const TDesC& aFilename)
+	{
+	TParse p;
+	TheFs.Parse(aFilename, p);
+	TDriveInfo dinfo;
+	TheFs.Drive(dinfo, TDriveUnit(p.Drive()));
+	TBool transactional = dinfo.iDriveAtt & KDriveAttTransaction;
+	if(transactional)
+		{
+		return ETransactional;
+		}
+	if(IsBlockAtomic(TDriveUnit(p.Drive())))
+		{
+		return EBlockAtomic;
+		}
+	return ESimple;
+	}
+/**
+@SYMTestCaseID          SYSLIB-STORE-CT-1160
+@SYMTestCaseDesc	    File server test
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for failure on call to file server
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_D void FailOnEveryFileServerCallL()
+	{
+	TheFs.Delete(FileNameA);
+
+	const TFileQoS KMediaType = MediaType(FileNameA);
+	_LIT(KSimpleText, "Simple");
+	_LIT(KAtomicText, "Atomic block \"write\"");
+	_LIT(KTransactionalText, "Transactional");
+	const TPtrC mediaType[ELastQoSType] = {KSimpleText(), KAtomicText(), KTransactionalText()};
+	test.Printf(_L("Media type: %S\r\n"), &mediaType[KMediaType]);
+
+	const TInt KStoreCommitted = KFailPoints[KMediaType][0];
+	const TInt KLastFail = KFailPoints[KMediaType][1];
+
+	const TInt KError = KErrNotReady;
+	const TInt KRootIdSizeBeforeStoreCommit = 0;
+	const TInt KRootIdSizeAfterStoreCommit = 6*sizeof(TStreamId);
+		
+	for (TInt fail=1;fail<=KLastFail+5;++fail)
+		{
+		store=CPermanentFileStore::ReplaceLC(TheFs,FileNameA,EFileWrite|EFileRead);
+		store->SetTypeL(KPermanentFileStoreLayoutUid);
+		TStreamId rootId = store->ExtendL();
+		store->SetRootL(rootId);
+		store->CommitL();
+		TRAPD(r,AlterStoreL(fail));
+		TheFs.SetErrorCondition(KErrNone);
+		if (fail<KLastFail)
+			test(r==KError);
+		else
+			test(r==KErrNone);
+		TRAP(r,store->RevertL());
+		if (r==KErrNotReady)
+			{
+			CleanupStack::PopAndDestroy();
+			store=CPermanentFileStore::OpenLC(TheFs,FileNameA,EFileWrite|EFileRead);
+			}
+		else
+			test(r==KErrNone);
+		CleanupStack::PopAndDestroy();
+//
+		// open read only
+		store=CPermanentFileStore::OpenLC(TheFs,FileNameA,EFileRead);
+		RStoreReadStream in;
+		in.OpenLC(*store,store->Root());
+		TInt size=in.Source()->SizeL();
+		if (fail<KStoreCommitted)
+			test(size==KRootIdSizeBeforeStoreCommit);
+		else //fail>=KStoreCommitted
+			test(size==KRootIdSizeAfterStoreCommit);
+		CleanupStack::PopAndDestroy(2);
+//
+		store=CPermanentFileStore::OpenLC(TheFs,FileNameA,EFileRead|EFileWrite);
+		store->ExtendL();
+		store->RevertL();
+		in.OpenLC(*store,store->Root());
+		size=in.Source()->SizeL();
+		if (fail<KStoreCommitted)
+			test(size==KRootIdSizeBeforeStoreCommit);
+		else //fail>=KStoreCommitted
+			test(size==KRootIdSizeAfterStoreCommit);
+		CleanupStack::PopAndDestroy(2);
+		}
+	}
+
+LOCAL_D void InitialseStoreWithDataL()
+	{
+	TheFs.Delete(FileNameB);
+	store=CPermanentFileStore::CreateLC(TheFs,FileNameB,EFileWrite|EFileRead);
+	store->SetTypeL(KPermanentFileStoreLayoutUid);
+	TStreamId rootId = store->ExtendL();
+	store->SetRootL(rootId);
+	store->CommitL();
+	CleanupStack::PopAndDestroy();
+
+	store=CPermanentFileStore::OpenLC(TheFs,FileNameB,EFileWrite|EFileRead);
+	TStreamId id2 = out.CreateLC(*store);
+	out << des2;
+	out.CommitL();
+	CleanupStack::PopAndDestroy();
+
+	TStreamId id3 = out.CreateLC(*store);
+	out << des3;
+	out.CommitL();
+	CleanupStack::PopAndDestroy();
+
+	out.ReplaceLC(*store,store->Root());
+	out << id2;
+	out << id3;
+	out.CommitL();
+	CleanupStack::PopAndDestroy();// out
+
+	store->CommitL();
+	CleanupStack::PopAndDestroy();// store
+	}
+
+LOCAL_D void AlterStoreDuringFileServerErrorL(TInt aError)
+	{
+	store=CPermanentFileStore::OpenLC(TheFs,FileNameB,EFileWrite|EFileRead);
+	in.OpenLC(*store,store->Root());
+	TStreamId id2;
+	TStreamId id3;
+	in >> id2;
+	in >> id3;
+	CleanupStack::PopAndDestroy();// in
+
+	out.ReplaceLC(*store,id2);
+	out << des4;
+	out.CommitL();
+	CleanupStack::PopAndDestroy();// out
+	TheFs.SetErrorCondition(aError);
+	out.ReplaceLC(*store,id3);
+	out << des5;
+	out.CommitL();
+	CleanupStack::PopAndDestroy();// out
+
+	store->CommitL();
+	CleanupStack::PopAndDestroy();// store
+	}
+
+LOCAL_D void TestStreamDataL(TInt aError)
+	{
+	store=CPermanentFileStore::OpenLC(TheFs,FileNameB,EFileWrite|EFileRead);
+	in.OpenLC(*store,store->Root());
+	TStreamId id2;
+	TStreamId id3;
+	in >> id2;
+	in >> id3;
+	CleanupStack::PopAndDestroy();// in
+
+	TBuf<16> buf;
+
+	in.OpenLC(*store,id2);
+	in >> buf;
+	if (aError==KErrNone)
+		test(buf==_L("4444"));// store committed
+	else
+		test(buf==_L("22"));// store reverted
+
+	CleanupStack::PopAndDestroy();// in
+
+	in.OpenLC(*store,id3);
+	in >> buf;
+	if (aError==KErrNone)
+		test(buf==_L("55555"));// store committed
+	else
+		test(buf==_L("333"));// store reverted
+
+	CleanupStack::PopAndDestroy();// in
+
+	CleanupStack::PopAndDestroy();// store
+	}
+
+LOCAL_D void ResetStreamDataL()
+	{
+	store=CPermanentFileStore::OpenLC(TheFs,FileNameB,EFileWrite|EFileRead);
+	in.OpenLC(*store,store->Root());
+	TStreamId id2;
+	TStreamId id3;
+	in >> id2;
+	in >> id3;
+	CleanupStack::PopAndDestroy();// in
+
+	out.ReplaceLC(*store,id2);
+	out << des2;
+	out.CommitL();
+	CleanupStack::PopAndDestroy();// out
+
+	out.ReplaceLC(*store,id3);
+	out << des3;
+	out.CommitL();
+	CleanupStack::PopAndDestroy();// out
+
+	store->CommitL();
+	CleanupStack::PopAndDestroy();// store
+	}
+/**
+@SYMTestCaseID          SYSLIB-STORE-CT-1161
+@SYMTestCaseDesc	    Tests for all errors on file server
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for stream data to a store
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_D void TestAllFsErrorL()
+	{
+	InitialseStoreWithDataL();
+	for (TInt error=0; error >= KErrDied; --error)
+		{
+		TRAPD(r,AlterStoreDuringFileServerErrorL(error));
+		TheFs.SetErrorCondition(KErrNone);
+		if (r!=KErrNone)
+			{
+			store = CPermanentFileStore::OpenLC(TheFs,FileNameB,EFileWrite|EFileRead);
+			store->RevertL();
+			CleanupStack::PopAndDestroy();// store
+			}
+		TestStreamDataL(error);
+		ResetStreamDataL();
+		}
+	}
+
+void RunTests()
+	{
+	setupTestDirectory();
+	__UHEAP_MARK;
+//
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-STORE-CT-1160 Random failure on every file server call "));
+	TRAPD(r,FailOnEveryFileServerCallL());
+	test(r==KErrNone);
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-STORE-CT-1161 Alter STORE during file server error "));
+	TRAP(r,TestAllFsErrorL());
+	test(r==KErrNone);
+	test.End();
+
+	TheFs.Delete(FileNameA);
+	TheFs.Delete(FileNameB);
+//
+	__UHEAP_MARKEND;
+	}
+
+#endif	// _DEBUG
+
+GLDEF_C TInt E32Main()
+    {// Test permanent file store.
+	test.Title();
+#ifdef _DEBUG
+	TInt r=TheFs.Connect();
+	test(r==KErrNone);
+	setupCleanup();
+	RunTests();
+	delete TheTrapCleanup;
+	TheFs.Close();
+#else
+	test.Start(_L("The tests are not valid in release mode"));
+	test.End();
+#endif
+	test.Close();
+	return 0;
+    }
+