persistentstorage/dbms/tdbms/t_dbtrans.cpp
changeset 0 08ec8eefde2f
child 55 44f437012c90
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/dbms/tdbms/t_dbtrans.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,384 @@
+// 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 <d32dbms.h>
+#include <s32file.h>
+#include <e32test.h>
+#include <e32math.h>
+#include <hal.h>
+
+static RTest TheTest(_L("t_dbtrans: Test DBMS transactions"));
+static RDbTable TheTable;
+static RFs TheFs;
+static RDbs TheDbs;
+static RDbNamedDatabase TheDatabase;
+
+static TFileName TheTestDbFileName;
+
+const TPtrC KTableName(_S("table"));
+const TPtrC KIndexInt=_S("int");
+const TPtrC KIndexText=_S("text");
+const TPtrC KColumnInt=_S("int");
+const TPtrC KColumnText=_S("text");
+const TPtrC KColumnComment=_S("comment");
+const TPtrC KCommentValue=_S("abcdefghijklmnopqrstuvwxyz");
+const TInt KRecords=2000;
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+static void CloseAll()
+	{
+	TheTable.Close();
+	TheDatabase.Close();
+	TheDbs.Close();
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+//Delete "aFullName" file.
+static void DeleteFile(const TDesC& aFullName)
+	{
+	RFs fsSession;
+	TInt err = fsSession.Connect();
+	if(err == KErrNone)
+		{
+		TEntry entry;
+		if(fsSession.Entry(aFullName, entry) == KErrNone)
+			{
+			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
+			if(err != KErrNone) 
+				{
+				TheTest.Printf(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
+				}
+			err = fsSession.Delete(aFullName);
+			if(err != KErrNone) 
+				{
+				TheTest.Printf(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
+				}
+			}
+		fsSession.Close();
+		}
+	else
+		{
+		TheTest.Printf(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
+		}
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+static void DestroyTestEnv()
+	{
+	CloseAll();
+	DeleteFile(TheTestDbFileName);
+	TheFs.Close();
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////
+//Tests macros and functions.
+//If (!aValue) then the test will be panicked, the test data files will be deleted.
+static void Check(TInt aValue, TInt aLine)
+	{
+	if(!aValue)
+		{
+		TheTest.Printf(_L("*** Boolean expression evaluated to false!\r\n"));
+		DestroyTestEnv();
+		TheTest(EFalse, aLine);
+		}
+	}
+//If (aValue != aExpected) then the test will be panicked, the test data files will be deleted.
+static void Check(TInt aValue, TInt aExpected, TInt aLine)
+	{
+	if(aValue != aExpected)
+		{
+		TheTest.Printf(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
+		DestroyTestEnv();
+		TheTest(EFalse, aLine);
+		}
+	}
+//Use these to test conditions.
+#define TEST(arg) ::Check((arg), __LINE__)
+#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
+
+//////////////////////////////////////////////////////
+
+static TInt TheCounterFreq = -10000000;
+const TInt KMicroSecIn1Sec = 1000000;
+
+TUint32 CalcTickDiff(TUint32 aStartTicks, TUint32 aEndTicks)
+	{
+	TInt64 diffTicks = (TInt64)aEndTicks - (TInt64)aStartTicks;
+	if(diffTicks < 0)
+		{
+		diffTicks = KMaxTUint32 + diffTicks + 1;
+		}
+	return (TUint32)diffTicks;
+	}
+
+//Prints aFastCount parameter (converted to us)
+void PrintFcDiffAsUs(const TDesC& aFormatStr, TUint32 aFastCount)
+	{
+	if(TheCounterFreq <= 0)
+		{
+		TEST2(HAL::Get(HAL::EFastCounterFrequency, TheCounterFreq), KErrNone);
+		TheTest.Printf(_L("Counter frequency=%d Hz\r\n"), TheCounterFreq);
+		}
+	double v = ((double)aFastCount * KMicroSecIn1Sec) / (double)TheCounterFreq;
+	TInt v2 = (TInt)v;
+	TheTest.Printf(aFormatStr, v2);
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+//
+// Prepare the test directory.
+//
+void CreateTestEnv()
+    {
+	TInt err = TheFs.Connect();
+	TheTest(err == KErrNone);
+
+	err = TheFs.MkDirAll(TheTestDbFileName);
+	TEST(err == KErrNone || err == KErrAlreadyExists);
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+class Progress
+	{
+	enum {ETotal=32};
+public:
+	Progress(TInt aCount);
+	void Next(TInt aStep);
+private:
+	TInt iCount;
+	TInt iPos;
+	};
+
+Progress::Progress(TInt aCount)
+	: iCount(aCount),iPos(0)
+	{}
+
+void Progress::Next(TInt aStep)
+	{
+	TInt next=(ETotal*(iCount-aStep))/iCount;
+	if (next!=iPos)
+		{
+		iPos=next;
+		}
+	}
+
+static void ProgressInc(RDbIncremental& inc,TInt aCount)
+	{
+	Progress progress(aCount);
+	while (aCount)
+		{
+		inc.Next(aCount);
+		progress.Next(aCount);
+		}
+	inc.Close();
+	}
+
+//
+// Create the database
+//
+static void CreateDatabase()
+	{
+	TInt err = TheDatabase.Replace(TheFs, TheTestDbFileName);
+	TEST2(err, KErrNone);
+	}
+
+//
+// Create the database
+//
+static void OpenDatabase()
+	{
+	TInt err = TheDatabase.Open(TheFs, TheTestDbFileName);
+	TEST2(err, KErrNone);
+	}
+
+static void CloseDatabase()
+	{
+	TheDatabase.Close();
+	}
+
+static void CreateTable()
+	{
+	TInt err = TheDatabase.Execute(_L("create table table (int integer,text varchar(8),comment varchar)"));
+	TEST2(err, KErrNone);
+	}
+
+static void WriteRecordsL(TInt aCount)
+	{
+	Progress write(aCount);
+	TDbColNo cInt,cText,cComment;
+	CDbColSet* set=TheTable.ColSetL();
+	cInt=set->ColNo(KColumnInt);
+	cText=set->ColNo(KColumnText);
+	cComment=set->ColNo(KColumnComment);
+	delete set;
+	TBuf<10> text;
+	TInt jj=0;
+	for (TInt ii=0;ii<aCount;++ii)
+		{
+		TheTable.InsertL();
+		jj=(jj+23);
+		if (jj>=aCount)
+			jj-=aCount;
+		TheTable.SetColL(cInt,jj);
+		text.Num(jj);
+		TheTable.SetColL(cText,text);
+		TheTable.SetColL(cComment,KCommentValue);
+		TheTable.PutL();
+		write.Next(aCount-ii-1);
+		}
+	}
+
+static TUint FileSize()
+	{
+	TEntry entry;
+	TEST2(TheFs.Entry(TheTestDbFileName, entry), KErrNone);
+	return entry.iSize;
+	}
+
+static void BuildTableL(TInt aCount, TBool aTransactions, TUint32& aTicks, TUint& aSize)
+	{
+	TUint size = FileSize();
+	TUint fc = User::FastCounter();
+	CreateTable();
+	if(aTransactions)
+		{
+		TheDatabase.Begin();
+		}
+	TEST2(TheTable.Open(TheDatabase, KTableName), KErrNone);
+	WriteRecordsL(aCount);
+	if(aTransactions)
+		{
+		TEST2(TheDatabase.Commit(), KErrNone);
+		}
+	TheTable.Close();
+	aTicks = CalcTickDiff(fc, User::FastCounter());
+	aSize = FileSize() - size;
+	}
+
+static void Execute(const TDesC& aSql)
+	{
+	RDbIncremental inc;
+	TInt step;
+	TEST2(inc.Execute(TheDatabase,aSql,step), KErrNone);
+	ProgressInc(inc,step);
+	}
+
+static void BreakIndexL()
+	{
+	TheDatabase.Begin();
+	TEST2(TheTable.Open(TheDatabase,KTableName), KErrNone);
+	TheTable.InsertL();
+	TheTable.SetColL(1,-1);
+	TheTable.PutL();
+	TheTable.Close();
+	TheDatabase.Rollback();
+	TEST(TheDatabase.IsDamaged());
+	}
+
+LOCAL_C void Recover()
+	{
+	RDbIncremental rec;
+	TInt step;
+	TEST2(rec.Recover(TheDatabase,step), KErrNone);
+	ProgressInc(rec,step);
+	TEST(!TheDatabase.IsDamaged());
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0637
+@SYMTestCaseDesc        Streaming conversions test
+@SYMTestPriority        Medium
+@SYMTestActions         Test the database definition and enquiry functions
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+static void TestL()
+	{
+	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0637 Build without transactions "));
+	CreateDatabase();
+	TUint32 ticks1;
+	TUint size1;
+	BuildTableL(KRecords, EFalse, ticks1, size1);
+	CloseDatabase();
+	
+	TheTest.Next(_L("Build with transactions"));
+	CreateDatabase();
+	TUint32 ticks2;
+	TUint size2;
+	BuildTableL(KRecords, ETrue, ticks2, size2);
+	
+	PrintFcDiffAsUs(_L("#### Without transactions, time=%d us\n"), ticks1);
+	PrintFcDiffAsUs(_L("#### With    transactions, time=%d us\n"), ticks2);
+	TheTest.Printf(_L("Transaction performance ratio (without trn:with trn): time %4.2f, size %4.2f\n"), TReal(ticks1) / TReal(ticks2), TReal(size1) / TReal(size2));
+	
+	TheTest.Next(_L("Build Int index"));
+	Execute(_L("create unique index int on table (int)"));
+	
+	TheTest.Next(_L("Break index"));
+	BreakIndexL();
+	
+	TheTest.Next(_L("Build Text index"));
+	Execute(_L("create unique index text on table (text)"));
+	
+	TheTest.Next(_L("Recover"));
+	TEST(TheDatabase.IsDamaged());
+	
+	CloseDatabase();
+	OpenDatabase();
+	TEST(TheDatabase.IsDamaged());
+	Recover();
+	
+	TheTest.Next(_L("Drop table"));
+	Execute(_L("drop table table"));
+	CloseDatabase();
+	}
+
+//Usage: "t_trans [<drive letter>:]]"
+TInt E32Main()
+    {
+	TheTest.Title();
+	
+	CTrapCleanup* tc = CTrapCleanup::New();
+	TheTest(tc != NULL);
+	
+	TBuf<256> cmdline;
+	User::CommandLine(cmdline);
+
+	TParse parse;
+
+	_LIT(KTestDatabase, "C:\\DBMS-TST\\T_TRANS.DB");
+	parse.Set(cmdline, &KTestDatabase, 0);
+	TheTestDbFileName.Copy(parse.FullName());
+	
+	__UHEAP_MARK;
+	
+	CreateTestEnv();
+	TRAPD(err, TestL());
+	TEST2(err, KErrNone);
+	DestroyTestEnv();
+
+	delete tc;
+
+	__UHEAP_MARKEND;
+	
+	TheTest.End();
+	TheTest.Close();
+	
+	return 0;
+    }