sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include <d32dbms.h>
sl@0: #include <e32math.h>
sl@0: #include <s32file.h>
sl@0: #include <e32test.h>
sl@0: #include "t_fail.h"
sl@0: 
sl@0: #include "crccheck.h"
sl@0: 
sl@0: #undef __UHEAP_MARK
sl@0: #define __UHEAP_MARK
sl@0: #undef __UHEAP_MARKEND
sl@0: #define __UHEAP_MARKEND
sl@0: #undef __UHEAP_CHECK
sl@0: #define __UHEAP_CHECK(a)
sl@0: 
sl@0: LOCAL_D TDBMS_CRCChecks TheCrcChecker;
sl@0: 
sl@0: #ifndef __linux__ //No CRC test on LINUX
sl@0: #ifdef __TOOLS2__
sl@0: const TPtrC	KCrcRecord=_L("\\epoc32\\winscw\\c\\dbms-tst\\T_FAIL.CRC");
sl@0: #else
sl@0: const TPtrC	KCrcRecord=_L("C:\\dbms-tst\\T_FAIL.CRC");
sl@0: #endif
sl@0: #endif
sl@0: 
sl@0: #define CRCCHECK  (TheCrcChecker.GenerateCrcL(KTestDatabase))
sl@0: 
sl@0: 
sl@0: _LIT(KTestTitle,"T_FAIL: DBMS Failure mode test");
sl@0: GLDEF_D RTest test(KTestTitle);
sl@0: GLDEF_D RDbs TheDbs;
sl@0: GLDEF_D RDbNamedDatabase TheDatabase;
sl@0: GLDEF_D TClientHeap KClientHeap;
sl@0: GLDEF_D TServerHeap KServerHeap;
sl@0: 
sl@0: 
sl@0: LOCAL_D CTrapCleanup* TheTrapCleanup;
sl@0: LOCAL_D RFs TheFs;
sl@0: LOCAL_D RDbView TheView;
sl@0: LOCAL_D RDbTable TheTable;
sl@0: LOCAL_D RDbRowSet::TAccess Access;
sl@0: LOCAL_D CDbColSet* TheColSet;
sl@0: LOCAL_D CDbKey* TheKey;
sl@0: LOCAL_D const TDesC* TheSql;
sl@0: LOCAL_D TBuf<64> TheFormat;
sl@0: 
sl@0: const TInt KTestCleanupStack=0x20;
sl@0: 
sl@0: #ifndef __TOOLS2__
sl@0: const TPtrC KTestDatabase=_L("C:\\dbms-tst\\t_fail.db");
sl@0: #else
sl@0: const TPtrC KTestDatabase=_L(".\\dbms-tst\\t_fail.db");
sl@0: #endif
sl@0: 
sl@0: _LIT(TableName,"Table1");
sl@0: _LIT(TableName2,"Table_two");
sl@0: _LIT(TableNameX,"Bad Table Name");
sl@0: _LIT(IndexName,"Index1");
sl@0: _LIT(IndexName2,"Index2");
sl@0: _LIT(Column1,"column_one");
sl@0: _LIT(Column1Fold,"COLUMN_ONE");
sl@0: _LIT(Column2,"column_2");
sl@0: _LIT(Column2X,"column_2%");
sl@0: _LIT(SimpleSql,"select * from Table1");
sl@0: _LIT(UpdateSql,"update Table1 SET column_2='hello'");
sl@0: 
sl@0: //const TPtrC ComplexSql(_S("select * from Table1 where column_one<0 and not column_one is null or column_2 not like '*fred*' and column_2>'m' order by column_one desc"));
sl@0: const TPtrC ComplexSql[]=
sl@0: 	{
sl@0: 	_S("select * from Table1 where column_one<0 and column_one is null"),
sl@0: 	_S("select * from Table1 where column_one<0 and (column_one is null and column_2 like '')"),
sl@0: 	_S("select * from Table1 where (column_one<0 and column_one is null) and column_2 like ''"),
sl@0: 	_S("select * from Table1 where (column_one<0 and column_one is null) and (column_2 like '' and column_one>0)"),
sl@0: 	_S("select * from Table1 where (column_one<0 and column_one is null) and (column_2 like '' and column_one>0 and column_one is null)"),
sl@0: 	_S("select * from Table1 where (column_one<0 and column_one is null and column_one = 10) and (column_2 like '' and column_one>0 and column_one is null)"),
sl@0: 	_S("select * from Table1 where column_one<0 and column_one is null and column_one = 10 and column_2 like '' and column_one>0 and column_one is null")
sl@0: 	};
sl@0: 
sl@0: struct SSqlErrors
sl@0: 	{
sl@0: 	const TText* iSql;
sl@0: 	TInt iError;
sl@0: 	};
sl@0: 
sl@0: LOCAL_D SSqlErrors const BadSql[]=
sl@0: 	{
sl@0: 		{_S("sponge"),KErrArgument},
sl@0: 		{_S("select * from widget"),KErrNotFound},
sl@0: 		{_S("select * from Table1 where x = 0"),KErrNotFound},
sl@0: 		{_S("select * from Table1 where x 0 like"),KErrArgument},
sl@0: 		{_S("select * from Table1 where column_2>'a' and column_one<'z'"),KErrGeneral},
sl@0: 		{_S("select from Table1"),KErrArgument},
sl@0: 		{_S("select x, from Table1"),KErrArgument},
sl@0: 		{_S("select x from Table1"),KErrNotFound},
sl@0: 		{_S("select column_2 column_one from Table1"),KErrArgument},
sl@0: 		{_S("select * from Table1 order by x"),KErrNotFound},
sl@0: 		{_S("select * from Table1 order column_one"),KErrArgument},
sl@0: 		{_S("select * from Table1 order by column_one down"),KErrArgument}
sl@0: 	};
sl@0: 
sl@0: GLDEF_C void Connect()
sl@0: 	{
sl@0: #ifndef __TOOLS2__
sl@0: 	TInt r=TheDbs.Connect();
sl@0: 	test (r==KErrNone);
sl@0: 	TheDbs.ResourceMark();
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: GLDEF_C void Disconnect()
sl@0: 	{
sl@0: #ifndef __TOOLS2__
sl@0: 	TheDbs.ResourceCheck();
sl@0: 	TheDbs.Close();
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version
sl@0: LOCAL_C void DbCreateL()
sl@0: 	{
sl@0: 	User::LeaveIfError(TheDatabase.Replace(TheFs,KTestDatabase,TheFormat));
sl@0: 	}
sl@0: 
sl@0: //SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version
sl@0: LOCAL_C void DbOpenL()
sl@0: 	{
sl@0: 	User::LeaveIfError(TheDatabase.Open(TheFs,KTestDatabase,TheFormat));
sl@0: 	CleanupClosePushL(TheDatabase);
sl@0: 	delete TheDatabase.TableNamesL();	// force a schema load
sl@0: 	CleanupStack::Pop();
sl@0: 	}
sl@0: 
sl@0: //SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version
sl@0: LOCAL_C void DbShareL()
sl@0: 	{
sl@0: 	User::LeaveIfError(TheDatabase.Open(TheDbs,KTestDatabase,TheFormat));
sl@0: 	CleanupClosePushL(TheDatabase);
sl@0: 	delete TheDatabase.TableNamesL();	// force a schema load
sl@0: 	CleanupStack::Pop();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-CT-0612
sl@0: @SYMTestCaseDesc        Database validity test
sl@0: @SYMTestPriority        Medium
sl@0: @SYMTestActions         Tests for opening and closing of database
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_C void TestOpen()
sl@0: 	{
sl@0: 	_LIT(KFileNotFound,"not a database");
sl@0: 	TInt r=TheDatabase.Open(TheFs,KFileNotFound);
sl@0: 	test (r==KErrNotFound || r==KErrPathNotFound);
sl@0: //
sl@0: 	_LIT(KPathNotFound,"C:\\not a path\\database.db");
sl@0: 	r=TheDatabase.Open(TheFs,KPathNotFound);
sl@0: #ifndef __TOOLS2__
sl@0: 	test (r==KErrPathNotFound);
sl@0: #else
sl@0: 	// Tools2 f32 does not return KErrPathNotFound
sl@0: 	test( (r==KErrPathNotFound) || (r==KErrNotFound));
sl@0: #endif
sl@0: //
sl@0: 	_LIT(KNotFormat,"not.a.dbx");
sl@0: 	r=TheDatabase.Open(TheFs,KFileNotFound,KNotFormat);
sl@0: 	test (r==KErrNotFound || r==KErrPathNotFound);
sl@0: //
sl@0: 	DbCreateL();
sl@0: 	TheDatabase.Close();
sl@0: 	TInt err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	r=TheDatabase.Open(TheFs,KTestDatabase,TUid::Uid(0x01234567).Name());
sl@0: 	test (r==KErrNone); // New code has no loadable drivers, it is irrelevant to expect error here
sl@0: 	TheDatabase.Close(); // We have added it here because previous statement does not return error anymore
sl@0: 	err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: //
sl@0: 	RFile f;
sl@0: 	r=f.Replace(TheFs,KTestDatabase,EFileWrite);
sl@0: 	test (r==KErrNone);
sl@0: 	TCheckedUid type(KDirectFileStoreLayoutUid);
sl@0: 	r=f.Write(type.Des());
sl@0: 	test (r==KErrNone);
sl@0: 	f.Close();
sl@0: 	r=TheDatabase.Open(TheFs,KTestDatabase);
sl@0: 	test (r==KErrNotSupported);
sl@0: //
sl@0: 	_LIT(KDefaultFormat,"epoc");
sl@0: 	r=TheDatabase.Open(TheFs,KTestDatabase,KDefaultFormat);
sl@0: 	test (r==KErrNotSupported); // We expect not supported db here
sl@0: 	}
sl@0: 
sl@0: class TClient : public TContext
sl@0: 	{
sl@0: public:
sl@0: 	TClient() {}
sl@0: private:
sl@0: 	void OpenDbL() const
sl@0: 		{DbOpenL();}
sl@0: 	};
sl@0: class TServer : public TContext
sl@0: 	{
sl@0: public:
sl@0: 	TServer() {}
sl@0: private:
sl@0: 	void OpenDbL() const
sl@0: 		{DbShareL();}
sl@0: 	};
sl@0: 
sl@0: const TClient KClient;
sl@0: const TServer KServer;
sl@0: 
sl@0: void TFail::Test(const THeapFail& aHeap,const TContext* aContext)
sl@0: 	{
sl@0: 	TInt ii;
sl@0: 	TInt errCode;
sl@0: 	for (ii=1;;++ii)
sl@0: 		{
sl@0: 		if (aContext)
sl@0: 			{
sl@0: 			TRAP(errCode, aContext->OpenDbL());
sl@0: 			if(errCode != KErrNone)
sl@0: 				return;
sl@0: 			}
sl@0: 		aHeap.Fail(ii);
sl@0: 		aHeap.Mark();
sl@0: 		TRAPD(r,RunL());
sl@0: 		aHeap.Reset();
sl@0: 		if (r==KErrNone)
sl@0: 			break;
sl@0: 		test(r==KErrNoMemory);
sl@0: 		if (aContext)
sl@0: 			{
sl@0: 			TheDatabase.Close();
sl@0: 			TRAPD(lc, errCode = CRCCHECK);
sl@0: 			test(errCode == KErrNone);
sl@0: 			test(lc == KErrNone);
sl@0: 			}
sl@0: 		aHeap.Check();
sl@0: 		}
sl@0: 	End();
sl@0: 	if (aContext)
sl@0: 		{
sl@0: 		TheDatabase.Close();
sl@0: 		TRAPD(lc, errCode = CRCCHECK);
sl@0: 		test(errCode == KErrNone);
sl@0: 		test(lc == KErrNone);
sl@0: 		}
sl@0: 	aHeap.Check();
sl@0: 	}
sl@0: 
sl@0: class TFailCreateDatabase : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{DbCreateL();}
sl@0: 	void End()
sl@0: 		{
sl@0: 		TheDatabase.Close();
sl@0: 		TInt err;
sl@0: 		TRAPD(lc, err = CRCCHECK);
sl@0: 		test(err == KErrNone);
sl@0: 		test(lc == KErrNone);
sl@0: 		}
sl@0: 	};
sl@0: 
sl@0: class TFailOpenDatabase : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{DbOpenL();}
sl@0: 	void End()
sl@0: 		{
sl@0: 		TheDatabase.Close();
sl@0: 		TInt err;
sl@0: 		TRAPD(lc, err = CRCCHECK);
sl@0: 		test(err == KErrNone);
sl@0: 		test(lc == KErrNone);
sl@0: 	   	}
sl@0: 	};
sl@0: 
sl@0: class TFailShareDatabase : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{DbShareL();}
sl@0: 	void End()
sl@0: 		{
sl@0: 		TheDatabase.Close();
sl@0: // Unfortunately it is not possible to generate CRC checks here. The
sl@0: // database on a number of occasions is still open by another instance.
sl@0: // This causes a KErrInUse in the CRC check code for Symbian, but
sl@0: // works on TOOLS2, thus giving probably spurious mismatches.
sl@0: //		TInt err;
sl@0: //		TRAPD(lc, err = CRCCHECK);
sl@0: //		RDebug::Print(_L("ERROR %d\n"), err);
sl@0: //		test(err == KErrNone);
sl@0: //		test(lc == KErrNone);
sl@0: 	   	}
sl@0: 	};
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-CT-0613
sl@0: @SYMTestCaseDesc        Tests for allocation failures on creating a database
sl@0: @SYMTestPriority        Medium
sl@0: @SYMTestActions         Tests for allocation failure for differently sourced databases
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_C void Origins()
sl@0: 	{
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0613 Allocation failures on Creating a database "));
sl@0: 	TFailCreateDatabase t1;
sl@0: 	t1.Test(KClientHeap);
sl@0: //
sl@0: 	test.Next(_L("Fail to create existing database"));
sl@0: #ifndef __TOOLS2__
sl@0: 	TUint att;
sl@0: 	TInt r=TheFs.Att(KTestDatabase,att);
sl@0: 	test (r==KErrNone);
sl@0: #else
sl@0: 	TInt r;
sl@0: #endif
sl@0: 	r=TheDatabase.Create(TheFs,KTestDatabase,TheFormat);
sl@0: 	test (r==KErrAlreadyExists);
sl@0: #ifndef __TOOLS2__
sl@0: 	r=TheFs.Att(KTestDatabase,att);
sl@0: 	test (r==KErrNone);
sl@0: #endif
sl@0: //
sl@0: 	test.Next(_L("Allocation failures on Open"));
sl@0: 	TFailOpenDatabase t2;
sl@0: 	t2.Test(KClientHeap);
sl@0: //
sl@0: 	test.Next(_L("Allocation failures on 1st Share"));
sl@0: 	Connect();
sl@0: 	TFailShareDatabase t3;
sl@0: 	t3.Test(KClientHeap);
sl@0: 	t3.Test(KServerHeap);
sl@0: //
sl@0: 	test.Next(_L("Allocation failures on 2nd Share"));
sl@0: 	DbShareL();
sl@0: 	RDbNamedDatabase temp=TheDatabase;TheDatabase=RDbNamedDatabase();
sl@0: 	t3.Test(KClientHeap);
sl@0: 	t3.Test(KServerHeap);
sl@0: 	temp.Close();
sl@0: 	Disconnect();
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: class TFailCreateTable : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{User::LeaveIfError(TheDatabase.CreateTable(TableName,*TheColSet));}
sl@0: 	};
sl@0: 
sl@0: class TFailAlterTable : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{User::LeaveIfError(TheDatabase.AlterTable(TableName,*TheColSet));}
sl@0: 	};
sl@0: 
sl@0: class TFailDropTable : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{User::LeaveIfError(TheDatabase.DropTable(TableName));}
sl@0: 	};
sl@0: 
sl@0: class TFailCreateIndex : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{User::LeaveIfError(TheDatabase.CreateIndex(IndexName,TableName,*TheKey));}
sl@0: 	};
sl@0: 
sl@0: class TFailDropIndex : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{User::LeaveIfError(TheDatabase.DropIndex(IndexName,TableName));}
sl@0: 	};
sl@0: 
sl@0: class TFailGetObject : public TFail
sl@0: 	{
sl@0: protected:
sl@0: 	void End()
sl@0: 		{delete iObject;}
sl@0: protected:
sl@0: 	CBase* iObject;
sl@0: 	};
sl@0: 
sl@0: class TFailDatabaseTables : public TFailGetObject
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{iObject=TheDatabase.TableNamesL();}
sl@0: 	};
sl@0: 
sl@0: class TFailDatabaseColSet : public TFailGetObject
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{iObject=TheDatabase.ColSetL(TableName);}
sl@0: 	};
sl@0: 
sl@0: class TFailDatabaseIndexes : public TFailGetObject
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{iObject=TheDatabase.IndexNamesL(TableName);}
sl@0: 	};
sl@0: 
sl@0: class TFailDatabaseKeys : public TFailGetObject
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{iObject=TheDatabase.KeyL(IndexName,TableName);}
sl@0: 	};
sl@0: 
sl@0: const TInt KRowCount=60;
sl@0: 
sl@0: LOCAL_C void WriteTableL()
sl@0: 	{
sl@0: 	DbOpenL();
sl@0: 	TInt r=TheTable.Open(TheDatabase,TableName);
sl@0: 	test (r==KErrNone);
sl@0: 	TheDatabase.Begin();
sl@0: 	for (TInt ii=0;ii<KRowCount;++ii)
sl@0: 		{
sl@0: 		TheTable.InsertL();
sl@0: 		TheTable.SetColL(1,TUint((ii*17)%KRowCount));
sl@0: 		TheTable.PutL();
sl@0: 		}
sl@0: 	r=TheDatabase.Commit();
sl@0: 	test (r==KErrNone);
sl@0: 	TheTable.Close();
sl@0: 	TheDatabase.Close();
sl@0: 	TInt err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void Database()
sl@0: 	{
sl@0: 	test.Start(_L("Adding and dropping tables"));
sl@0: 	DbCreateL();
sl@0: // ensure the database locking list has been allocated
sl@0: 	TheDatabase.Begin();
sl@0: 	TheDatabase.Commit();
sl@0: //
sl@0: 	CDbColSet *col=CDbColSet::NewLC();
sl@0: //
sl@0: 	test.Next(_L("Empty Column Set"));
sl@0: 	__UHEAP_MARK;
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Invalid table name"));
sl@0: 	col->AddL(TDbCol(Column1,EDbColInt32));
sl@0: 	__UHEAP_MARK;
sl@0: 	test(TheDatabase.CreateTable(TableNameX,*col)!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Invalid column name"));
sl@0: 	col->AddL(TDbCol(Column2X,EDbColBit));
sl@0: 	__UHEAP_MARK;
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Duplicate column name"));
sl@0: 	col->Remove(Column2X);
sl@0: 	col->AddL(TDbCol(Column1Fold,EDbColBit));
sl@0: 	__UHEAP_MARK;
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Invalid column type"));
sl@0: 	col->Remove(Column1);
sl@0: 	col->AddL(TDbCol(Column2,TDbColType(-1)));
sl@0: 	__UHEAP_MARK;
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Invalid maximum length"));
sl@0: 	col->Remove(Column2);
sl@0: 	col->AddL(TDbCol(Column2,EDbColInt32,0));
sl@0: 	__UHEAP_MARK;
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Invalid attributes"));
sl@0: 	col->Remove(Column2);
sl@0: 	TDbCol cc(Column2,EDbColInt32);
sl@0: 	cc.iAttributes=13;
sl@0: 	col->AddL(cc);
sl@0: 	__UHEAP_MARK;
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Adding/dropping a table name twice"));
sl@0: 	col->Remove(Column2);
sl@0: 	col->AddL(TDbCol(Column2,EDbColText8));
sl@0: 	__UHEAP_MARK;
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)==KErrNone);
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)==KErrAlreadyExists);
sl@0: 	test(TheDatabase.DropTable(TableNameX)!=KErrNone);
sl@0: 	test(TheDatabase.DropTable(TableName)==KErrNone);
sl@0: 	test(TheDatabase.DropTable(TableName)==KErrNotFound);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Adding and dropping indexes"));
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)==KErrNone);
sl@0: 	TheDatabase.Close();
sl@0: 	TInt err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	CDbKey *key=CDbKey::NewLC();
sl@0: 	__UHEAP_MARK;
sl@0: 	DbOpenL();
sl@0: 	test(TheDatabase.CreateIndex(IndexName,TableName,*key)!=KErrNone);
sl@0: 	TheDatabase.Close();
sl@0: 	err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: 	key->AddL(Column2X());
sl@0: 	__UHEAP_MARK;
sl@0: 	DbOpenL();
sl@0: 	test(TheDatabase.CreateIndex(IndexName,TableName,*key)!=KErrNone);
sl@0: 	TheDatabase.Close();
sl@0: 	err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: 	key->Clear();
sl@0: 	key->AddL(Column1());
sl@0: 	__UHEAP_MARK;
sl@0: 	DbOpenL();
sl@0: 	test(TheDatabase.CreateIndex(TableNameX,TableName,*key)!=KErrNone);
sl@0: 	TheDatabase.Close();
sl@0: 	err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	__UHEAP_CHECK(0);
sl@0: 	DbOpenL();
sl@0: 	test(TheDatabase.CreateIndex(IndexName,TableNameX,*key)!=KErrNone);
sl@0: 	TheDatabase.Close();
sl@0: 	err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: 	__UHEAP_MARK;
sl@0: 	DbOpenL();
sl@0: 	test(TheDatabase.CreateIndex(IndexName,TableName,*key)==KErrNone);
sl@0: 	test(TheDatabase.CreateIndex(IndexName,TableName,*key)==KErrAlreadyExists);
sl@0: 	test(TheDatabase.DropIndex(TableNameX,TableName)!=KErrNone);
sl@0: 	test(TheDatabase.DropIndex(IndexName,TableNameX)!=KErrNone);
sl@0: 	test(TheDatabase.DropIndex(IndexName,TableName)==KErrNone);
sl@0: 	test(TheDatabase.DropIndex(IndexName,TableName)==KErrNotFound);
sl@0: 	test(TheDatabase.DropTable(TableName)==KErrNone);
sl@0: 	test(TheDatabase.DropIndex(IndexName,TableName)==KErrNotFound);
sl@0: 	TheDatabase.Close();
sl@0: 	err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Allocation failure during DDL"));
sl@0: 	TFailCreateTable fct;
sl@0: 	TFailAlterTable fat;
sl@0: 	TFailDropTable fdt;
sl@0: 	TFailCreateIndex fci;
sl@0: 	TFailDropIndex fdi;
sl@0: 	TheColSet=CDbColSet::NewL();
sl@0: 	TheColSet->AddL(TDbCol(Column1,EDbColUint16));
sl@0: 	TheKey=CDbKey::NewL();
sl@0: 	TheKey->AddL(Column1());
sl@0: 	fct.Test(KClientHeap,KClient);
sl@0: 	WriteTableL();
sl@0: 	TheColSet->AddL(TDbCol(Column2,EDbColText));
sl@0: 	fat.Test(KClientHeap,KClient);
sl@0: 	fci.Test(KClientHeap,KClient);
sl@0: 	fdi.Test(KClientHeap,KClient);
sl@0: 	fdt.Test(KClientHeap,KClient);
sl@0: //
sl@0: 	test.Next(_L("Allocation failure during server DDL"));
sl@0: 	Connect();
sl@0: 	TheColSet->Remove(Column2);
sl@0: 	fct.Test(KClientHeap,KServer);
sl@0: 	WriteTableL();
sl@0: 	TheColSet->AddL(TDbCol(Column2,EDbColText));
sl@0: 	fat.Test(KClientHeap,KServer);
sl@0: 	fci.Test(KClientHeap,KServer);
sl@0: 	fdi.Test(KClientHeap,KServer);
sl@0: 	fdt.Test(KClientHeap,KServer);
sl@0: //
sl@0: 	TheColSet->Remove(Column2);
sl@0: 	fct.Test(KServerHeap,KServer);
sl@0: 	WriteTableL();
sl@0: 	TheColSet->AddL(TDbCol(Column2,EDbColText));
sl@0: 	fat.Test(KServerHeap,KServer);
sl@0: 	fci.Test(KServerHeap,KServer);
sl@0: 	fdi.Test(KServerHeap,KServer);
sl@0: 	fdt.Test(KServerHeap,KServer);
sl@0: 	Disconnect();
sl@0: //
sl@0: 	delete TheColSet;
sl@0: 	delete TheKey;
sl@0: 
sl@0: //
sl@0: 	test.Next(_L("Allocation failure on schema enquiry"));
sl@0: 	DbCreateL();
sl@0: 	test(TheDatabase.CreateTable(TableName,*col)==KErrNone);
sl@0: 	test(TheDatabase.CreateIndex(IndexName,TableName,*key)==KErrNone);
sl@0: 	CleanupStack::PopAndDestroy(2);	// columns set and key
sl@0: 	TheDatabase.Close();
sl@0: 	err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	TFailDatabaseTables t4;
sl@0: 	TFailDatabaseColSet t5;
sl@0: 	TFailDatabaseIndexes t6;
sl@0: 	TFailDatabaseKeys t7;
sl@0: 	t4.Test(KClientHeap,KClient);
sl@0: 	t5.Test(KClientHeap,KClient);
sl@0: 	t6.Test(KClientHeap,KClient);
sl@0: 	t7.Test(KClientHeap,KClient);
sl@0: //
sl@0: 	test.Next(_L("Allocation failure on server schema enquiry"));
sl@0: 	Connect();
sl@0: 	t4.Test(KClientHeap,KServer);
sl@0: 	t4.Test(KServerHeap,KServer);
sl@0: 	t5.Test(KClientHeap,KServer);
sl@0: 	t5.Test(KServerHeap,KServer);
sl@0: 	t6.Test(KClientHeap,KServer);
sl@0: 	t6.Test(KServerHeap,KServer);
sl@0: 	t7.Test(KClientHeap,KServer);
sl@0: 	t7.Test(KServerHeap,KServer);
sl@0: 	Disconnect();
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: class TFailOpenTable : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{User::LeaveIfError(TheTable.Open(TheDatabase,TableName,Access));}
sl@0: 	void End()
sl@0: 		{TheTable.Close();}
sl@0: 	};
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-CT-0614
sl@0: @SYMTestCaseDesc        Tests for allocation failure on opening and closing of database
sl@0: @SYMTestPriority        Medium
sl@0: @SYMTestActions         Tests for opening and closing of database
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_C void TestTable(const THeapFail& aHeap,const TContext& aContext)
sl@0: 	{
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0614 Allocation failure on Open "));
sl@0: 	TFailOpenTable fot;
sl@0: 	Access=RDbRowSet::EUpdatable;
sl@0: 	fot.Test(aHeap,aContext);
sl@0: 	Access=RDbRowSet::EReadOnly;
sl@0: 	fot.Test(aHeap,aContext);
sl@0: 	Access=RDbRowSet::EInsertOnly;
sl@0: 	fot.Test(aHeap,aContext);
sl@0: //
sl@0: 	test.Next(_L("Open invalid table"));
sl@0: 	aContext.OpenDbL();
sl@0: 	__UHEAP_MARK;
sl@0: 	TInt r=TheTable.Open(TheDatabase,TableNameX);
sl@0: 	test (r!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Set invalid index"));
sl@0: 	r=TheTable.Open(TheDatabase,TableName);
sl@0: 	test (r==KErrNone);
sl@0: 	__UHEAP_MARK;
sl@0: 	r=TheTable.SetIndex(IndexName2);
sl@0: 	test (r!=KErrNone);
sl@0: 	__UHEAP_MARKEND;
sl@0: //
sl@0: 	test.Next(_L("Allocation failure on 2nd Open"));
sl@0: 	RDbTable table(TheTable);
sl@0: 	Access=RDbRowSet::EUpdatable;
sl@0: 	fot.Test(aHeap);
sl@0: 	Access=RDbRowSet::EReadOnly;
sl@0: 	fot.Test(aHeap);
sl@0: 	Access=RDbRowSet::EInsertOnly;
sl@0: 	fot.Test(aHeap);
sl@0: 	table.Close();
sl@0: 	TheDatabase.Close();
sl@0: 	r = CRCCHECK;
sl@0: 	test(r == KErrNone);
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void TestTableDDL(const TContext& aContext)
sl@0: 	{
sl@0: 	test.Start(_L("DDL while open"));
sl@0: 	aContext.OpenDbL();
sl@0: 	TInt r=TheTable.Open(TheDatabase,TableName);
sl@0: 	test (r==KErrNone);
sl@0: 	CDbColSet* set=CDbColSet::NewLC();
sl@0: 	set->AddL(TDbCol(Column1,EDbColText));
sl@0: 	r=TheDatabase.CreateTable(TableName2,*set);
sl@0: 	test (r==KErrNone);
sl@0: 	TRAP(r,TheTable.CountL(TheTable.EQuick));
sl@0: 	test (r==KErrNone);
sl@0: 	TheTable.Close();
sl@0: 	r=TheTable.Open(TheDatabase,TableName2);
sl@0: 	test (r==KErrNone);
sl@0: //
sl@0: 	set->AddL(TDbCol(Column2,EDbColUint32));
sl@0: 	r=TheDatabase.AlterTable(TableName2,*set);
sl@0: 	test (r==KErrNone);
sl@0: 	CleanupStack::PopAndDestroy();		// set
sl@0: 	TRAP(r,TheTable.CountL(TheTable.EQuick));
sl@0: 	test (r==KErrDisconnected);
sl@0: 	TheTable.Reset();
sl@0: 	TRAP(r,TheTable.CountL(TheTable.EQuick));
sl@0: 	test (r==KErrDisconnected);
sl@0: 	TheTable.Close();
sl@0: 	r=TheTable.Open(TheDatabase,TableName2);
sl@0: 	test (r==KErrNone);
sl@0: //
sl@0: 	CDbKey* key=CDbKey::NewLC();
sl@0: 	key->AddL(Column2());
sl@0: 	r=TheDatabase.CreateIndex(IndexName2,TableName,*key);
sl@0: 	test (r==KErrNone);
sl@0: 	TRAP(r,TheTable.CountL(TheTable.EQuick));
sl@0: 	test (r==KErrNone);
sl@0: 	r=TheDatabase.DropIndex(IndexName2,TableName);
sl@0: 	test (r==KErrNone);
sl@0: 	TRAP(r,TheTable.CountL(TheTable.EQuick));
sl@0: 	test (r==KErrNone);
sl@0: //
sl@0: 	r=TheDatabase.CreateIndex(IndexName,TableName2,*key);
sl@0: 	test (r==KErrNone);
sl@0: 	CleanupStack::PopAndDestroy();	// key
sl@0: 	TRAP(r,TheTable.CountL(TheTable.EQuick));
sl@0: 	test (r==KErrDisconnected);
sl@0: 	TheTable.Close();
sl@0: 	r=TheTable.Open(TheDatabase,TableName2);
sl@0: 	test (r==KErrNone);
sl@0: //
sl@0: 	r=TheDatabase.DropIndex(IndexName,TableName2);
sl@0: 	test (r==KErrNone);
sl@0: 	TRAP(r,TheTable.CountL(TheTable.EQuick));
sl@0: 	test (r==KErrDisconnected);
sl@0: 	TheTable.Close();
sl@0: 	r=TheTable.Open(TheDatabase,TableName2);
sl@0: 	test (r==KErrNone);
sl@0: //
sl@0: 	r=TheDatabase.DropTable(TableName2);
sl@0: 	test (r==KErrNone);
sl@0: 	TRAP(r,TheTable.CountL(TheTable.EQuick));
sl@0: 	test (r==KErrDisconnected);
sl@0: 	TheTable.Close();
sl@0: 	TheDatabase.Close();
sl@0: 	r = CRCCHECK;
sl@0: 	test(r == KErrNone);
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void Table()
sl@0: 	{
sl@0: 	test.Start(_L("Testing Client-side"));
sl@0: 	TestTable(KClientHeap,KClient);
sl@0: 	TestTableDDL(KClient);
sl@0: 	test.Next(_L("Testing Client-Server"));
sl@0: 	Connect();
sl@0: 	TestTable(KClientHeap,KServer);
sl@0: 	TestTable(KServerHeap,KServer);
sl@0: 	TestTableDDL(KServer);
sl@0: 	Disconnect();
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: class TFailExecuteSQL : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{User::LeaveIfError(TheDatabase.Execute(*TheSql));}
sl@0: 	void End()
sl@0: 		{}
sl@0: 	};
sl@0: 
sl@0: class TFailPrepareView : public TFail
sl@0: 	{
sl@0: 	void RunL()
sl@0: 		{User::LeaveIfError(TheView.Prepare(TheDatabase,*TheSql,Access));}
sl@0: 	void End()
sl@0: 		{TheView.Close();}
sl@0: 	};
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-CT-0615
sl@0: @SYMTestCaseDesc        Tests for allocation failure on prepare
sl@0: @SYMTestPriority        Medium
sl@0: @SYMTestActions         Tests for error on updating a row set data
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_C void TestView(const THeapFail& aHeap,const TContext& aContext)
sl@0: 	{
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0615 Allocation failure on Prepare "));
sl@0: 	TFailPrepareView fpv;
sl@0: 	TheSql=&SimpleSql;
sl@0: 	Access=RDbRowSet::EUpdatable;
sl@0: 	fpv.Test(aHeap,aContext);
sl@0: 	Access=RDbRowSet::EReadOnly;
sl@0: 	fpv.Test(aHeap,aContext);
sl@0: 	Access=RDbRowSet::EInsertOnly;
sl@0: 	fpv.Test(aHeap,aContext);
sl@0: //
sl@0: 	test.Next(_L("Allocation failure on Prepare (complex SQL)"));
sl@0: 	for (TUint ii=0;ii<sizeof(ComplexSql)/sizeof(ComplexSql[0]);++ii)
sl@0: 		{
sl@0: 		TheSql=&ComplexSql[ii];
sl@0: 		Access=RDbRowSet::EUpdatable;
sl@0: 		fpv.Test(aHeap,aContext);
sl@0: 		}
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-CT-0616
sl@0: @SYMTestCaseDesc        Bad SQL query test 
sl@0: @SYMTestPriority        Medium
sl@0: @SYMTestActions         Test for bad query
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_C void TestSQL(const TContext& aContext)
sl@0: 	{
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0616 Bad SQL "));
sl@0: 	aContext.OpenDbL();
sl@0: 	for (TUint ii=0;ii<sizeof(BadSql)/sizeof(BadSql[0]);++ii)
sl@0: 		test(TheView.Prepare(TheDatabase,TPtrC(BadSql[ii].iSql))==BadSql[ii].iError);
sl@0: 	TheDatabase.Close();
sl@0: 	TInt err = CRCCHECK;
sl@0: 	test(err == KErrNone);
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-CT-0617
sl@0: @SYMTestCaseDesc        Tests for updation of an SQL statement
sl@0: @SYMTestPriority        Medium
sl@0: @SYMTestActions         Tests for update SQL statement
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_C void TestUpdateSQL(const THeapFail& aHeap,const TContext& aContext)
sl@0: 	{
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0617 Test for UPDATE SQL statement "));
sl@0: 	TFailExecuteSQL fsql;
sl@0: 	TheSql=&UpdateSql;
sl@0: 	fsql.Test(aHeap,aContext);
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void View()
sl@0: 	{
sl@0: 	test.Start(_L("Client side"));
sl@0: 	TestView(KClientHeap,KClient);
sl@0: 	TestSQL(KClient);
sl@0: 	test.Next(_L("Client-Server"));
sl@0: 	Connect();
sl@0: 	TestView(KClientHeap,KServer);
sl@0: 	TestView(KServerHeap,KServer);
sl@0: 	TestSQL(KServer);
sl@0: 	TestUpdateSQL(KClientHeap,KClient);
sl@0: 	TestUpdateSQL(KServerHeap,KClient);
sl@0: 	Disconnect();
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: //TFailIncrementalUpdate implements the base class' virtual methods - RunL() and End().
sl@0: //TFailIncrementalUpdate::RunL() is called by the base class' Test() method, which simulates
sl@0: //OOM failures and checks the behaviour of the "incremental update" statement used by RunL().
sl@0: class TFailIncrementalUpdate : public TFail
sl@0: 	{
sl@0: 	virtual void RunL()
sl@0: 		{
sl@0: 		RDbUpdate dbUpdate;
sl@0: 		CleanupClosePushL(dbUpdate);
sl@0: 		User::LeaveIfError(dbUpdate.Execute(TheDatabase, _L("UPDATE A SET Name = 'ModifiedNameString' WHERE Id2 > 10")));
sl@0: 		TInt step = 0;
sl@0: 		for(TInt err=1;err>0;++step)
sl@0: 			{
sl@0: 			err = dbUpdate.Next();
sl@0: 			User::LeaveIfError(err);
sl@0: 			}
sl@0: 		test(step > 1);//just to be sure that the test executes dbUpdate.Next() more than once
sl@0: 		CleanupStack::PopAndDestroy(&dbUpdate);
sl@0: 		}
sl@0: 	virtual void End()
sl@0: 		{
sl@0: 		TheDatabase.Close();
sl@0: 		TInt err;
sl@0: 		TRAPD( lc, err = CRCCHECK);
sl@0: 		test(err == KErrNone);
sl@0: 		test(lc == KErrNone);
sl@0: 		}
sl@0: 	};	
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-DBMS-UT-3414
sl@0: @SYMTestCaseDesc        "Incremental update" operations - OOM test.
sl@0: @SYMTestPriority        High
sl@0: @SYMTestActions         Create a test database with one table and insert some records there (> 100).
sl@0: 						Run an "incremental update" operation in OOM loop.
sl@0: @SYMTestExpectedResults The test should not fail or panic.
sl@0: @SYMDEF INC101720
sl@0: */
sl@0: LOCAL_C void IncrementalUpdateTest(const THeapFail& aHeap)
sl@0: 	{
sl@0: 	//Create a test shared database with a table
sl@0: 	TheDatabase.Close();
sl@0: 	TInt err, lc;
sl@0: #ifndef __TOOLS2__
sl@0: 	TheDbs.Close();
sl@0: #endif
sl@0: 	TRAP(lc, err = CRCCHECK);
sl@0: 	test(err == KErrNone);
sl@0: 	test(lc == KErrNone);
sl@0: #ifndef __TOOLS2__
sl@0: 	err = TheDbs.Connect();
sl@0: 	test(err == KErrNone);
sl@0: #endif
sl@0: 	err = TheDatabase.Replace(TheFs, KTestDatabase);
sl@0: 	test(err == KErrNone);
sl@0: 	TheDatabase.Close();
sl@0: 	TRAP(lc, err = CRCCHECK);
sl@0: 	test(err == KErrNone);
sl@0: 	test(lc == KErrNone);
sl@0: 	err = TheDatabase.Open(TheDbs, KTestDatabase);
sl@0: 	test(err == KErrNone);
sl@0: 	//Create a test table and fill the table with enough test records (> 100)
sl@0: 	err = TheDatabase.Execute(_L("CREATE TABLE A(Id COUNTER, Id2 INTEGER, Name LONG VARCHAR)"));	
sl@0: 	test(err == KErrNone);
sl@0: 	const TInt KTestRecCount = 110;
sl@0: 	err = TheDatabase.Begin();	
sl@0: 	test(err == KErrNone);
sl@0: 	for(TInt i=0;i<KTestRecCount;++i)
sl@0: 		{
sl@0: 		_LIT(KSqlFmtStr, "INSERT INTO A(Id2, Name) VALUES(%d, 'TestNameString')");
sl@0: 		TBuf<100> sql;
sl@0: //		TUint32 id = Math::Random() % KTestRecCount;
sl@0: 		TUint32 id = (i^0x55555555) % KTestRecCount;
sl@0: 		sql.Format(KSqlFmtStr, id + 1);
sl@0: 		err = TheDatabase.Execute(sql);
sl@0: 		test(err == 1);
sl@0: 		}
sl@0: 	err = TheDatabase.Commit();	
sl@0: 	test(err == KErrNone);
sl@0: 	//The OOM test
sl@0: 	TFailIncrementalUpdate testObj;
sl@0: 	testObj.Test(aHeap);
sl@0: 	//Cleanup
sl@0: 	TheDatabase.Close();
sl@0: #ifndef __TOOLS2__
sl@0: 	TheDbs.Close();
sl@0: #endif
sl@0: 	TRAP(lc, err = CRCCHECK);
sl@0: 	test(err == KErrNone);
sl@0: 	test(lc == KErrNone);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // Testing the DBMS for failure modes
sl@0: //
sl@0: LOCAL_C void doMain()
sl@0: 	{
sl@0: 	test.Start(_L("Class RDbNamedDatabase"));
sl@0: 	__UHEAP_MARK;
sl@0: 	Origins();
sl@0: 	__UHEAP_CHECK(0);
sl@0: 	__UHEAP_MARK;
sl@0: //  secure shared, not supported on tools2.
sl@0: //	Origins2();
sl@0: 
sl@0: 	__UHEAP_CHECK(0);
sl@0: 	test.Next(_L("Class RDbDatabase"));
sl@0: 	Database();
sl@0: 	__UHEAP_CHECK(0);
sl@0: 	test.Next(_L("Class RDbTable"));
sl@0: 	Table();
sl@0: 	__UHEAP_CHECK(0);
sl@0: 	test.Next(_L("Class RDbView"));
sl@0: 	View();
sl@0: 	__UHEAP_MARKEND;
sl@0: 	test.End();
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // Prepare the test directory.
sl@0: //
sl@0: LOCAL_C void setupTestDirectory()
sl@0:     {
sl@0: 	TInt r=TheFs.Connect();
sl@0: 	test(r==KErrNone);
sl@0: //
sl@0: 	r=TheFs.MkDir(KTestDatabase);
sl@0: 	test(r==KErrNone || r==KErrAlreadyExists);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // Initialise the cleanup stack.
sl@0: //
sl@0: LOCAL_C void setupCleanup()
sl@0:     {
sl@0: 	TheTrapCleanup=CTrapCleanup::New();
sl@0: 	test(TheTrapCleanup!=NULL);
sl@0: 	TRAPD(r,\
sl@0: 		{\
sl@0: 		for (TInt i=KTestCleanupStack;i>0;i--)\
sl@0: 			CleanupStack::PushL((TAny*)0);\
sl@0: 		CleanupStack::Pop(KTestCleanupStack);\
sl@0: 		});
sl@0: 	test(r==KErrNone);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void DeleteDataFile(const TDesC& aFullName)
sl@0: 	{
sl@0: 	RFs fsSession;
sl@0: 	TInt err = fsSession.Connect();
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		TEntry entry;
sl@0: 		if(fsSession.Entry(aFullName, entry) == KErrNone)
sl@0: 			{
sl@0: 			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
sl@0: 			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
sl@0: 			if(err != KErrNone) 
sl@0: 				{
sl@0: 				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
sl@0: 				}
sl@0: 			err = fsSession.Delete(aFullName);
sl@0: 			if(err != KErrNone) 
sl@0: 				{
sl@0: 				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
sl@0: 				}
sl@0: 			}
sl@0: 		fsSession.Close();
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: GLDEF_C TInt E32Main()
sl@0: 	{
sl@0: 	test.Title();
sl@0: 	setupTestDirectory();
sl@0: 	setupCleanup();
sl@0: 	__UHEAP_MARK;
sl@0: //
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0612 Locating a database "));
sl@0: 	TRAPD(r,TestOpen());
sl@0: 	test(r==KErrNone);
sl@0: 	
sl@0: //  These are in t_fail2, secure shared tests, unsupported.
sl@0: //	PrepareDbFmtString();
sl@0: //	TRAP(r,TestOpen2());
sl@0: //	test(r==KErrNone);
sl@0: 
sl@0: 	test.Next(_L("Standard database"));
sl@0: 	TRAP(r,doMain());
sl@0: 	test(r==KErrNone);
sl@0: 	test.Next(_L("Secure database"));
sl@0: 	TRAP(r,doMain());
sl@0: 	test(r==KErrNone);
sl@0: 	test.Next(_L("ISAM database"));
sl@0: 	TheFormat=_S("epoc[12345678]");
sl@0: 	TRAP(r,Origins());
sl@0: 	test(r==KErrNone);
sl@0: 
sl@0: //	TRAP(r,Origins2());
sl@0: //	test(r==KErrNone);
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-3414 \"Incremental update\" - client test "));
sl@0: 	IncrementalUpdateTest(KClientHeap);
sl@0: 	test.End();
sl@0: 	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-UT-3414 \"Incremental update\" - client-server test "));
sl@0: 	IncrementalUpdateTest(KServerHeap);
sl@0: 	test.End();
sl@0: 	test.Printf(_L("Waiting for server exit\n"));
sl@0: 	const TUint KExitDelay=6*0x100000;	// ~6 seconds
sl@0: 	User::After(KExitDelay);
sl@0: 
sl@0: 	::DeleteDataFile(KTestDatabase);		// clean up data file used by this test - must be done before call to End() - DEF047652
sl@0: 
sl@0: #ifndef __linux__
sl@0: 	TInt err;
sl@0: #ifndef __TOOLS2__
sl@0: 	TRAPD(lc, err = TheCrcChecker.DumpCrcRecordsL(KCrcRecord));
sl@0: 	test(err==KErrNone);
sl@0: 	test(lc==KErrNone);
sl@0: #else
sl@0: 	TRAPD(lc, err = TheCrcChecker.ValidateCrcRecordsL(KCrcRecord));
sl@0: 	TPtrC errmsg;
sl@0: 	TheCrcChecker.ErrorReportL(err, errmsg);
sl@0: 	RDebug::Print(errmsg);
sl@0: 	test(err==KErrNone || err==TDBMS_CRCChecks::ECrcCheckOk);
sl@0: #endif
sl@0: #endif
sl@0: 
sl@0: 	test.End();
sl@0: 
sl@0: 	__UHEAP_MARKEND;
sl@0: 
sl@0: 	delete TheTrapCleanup;
sl@0: 	TheFs.Close();
sl@0: 	test.Close();
sl@0: 	return 0;
sl@0: 	}