diff -r 000000000000 -r 08ec8eefde2f persistentstorage/dbms/tdbms/t_dbtrans.cpp --- /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 +#include +#include +#include +#include + +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) + 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 [:]]" +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; + }