persistentstorage/dbms/tdbms/t_dbbug.cpp
changeset 0 08ec8eefde2f
child 23 26645d81f48d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/dbms/tdbms/t_dbbug.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,623 @@
+// 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:
+// Test code for bugs that have been fixed, to help prevent regression
+// 
+//
+
+#include <d32dbms.h>
+#include <f32file.h>
+#include <e32test.h>
+#include <s32mem.h>
+
+LOCAL_D RTest test(_L("t_dbbug"));
+LOCAL_D CTrapCleanup* TheTrapCleanup;
+LOCAL_D RFs TheFs;
+LOCAL_D RDbNamedDatabase TheDatabase;
+
+const TInt KTestCleanupStack=0x40;
+
+void Check(TInt aValue,TInt aExpected,TInt aLine)
+	{
+	if (aValue!=aExpected)
+		{
+		test.Printf(_L("*** Expected %d: got %d\r\n"),aExpected,aValue);
+		test.operator()(EFalse,aLine);
+		}
+	}
+#define test2(a,b) Check(a,b,__LINE__)
+
+static void Print(const TText* aString)
+	{
+	test.Printf(_L("%s\n"),aString);
+	}
+
+////////////////////////////////////////////
+
+_LIT(KTestDatabase,"c:\\dbms-tst\\bug.db");
+_LIT(KTableA,"A");
+_LIT(KTableB,"B");
+_LIT(KTableC,"C");
+
+class Defect_590829
+	{
+public:
+	static void TestL();
+	static const TDesC& Name();
+	};
+
+
+const TDesC& Defect_590829::Name()
+	{
+	_LIT(KName,"590829");
+	return KName;
+	}
+
+/////////////////////////////////////////////////
+
+// Length of text data used for each entry. This will be
+// equivalent to 400 bytes for ansi characters. The number of
+// bytes must not be less than 256 (or 128 for this const).
+// If it is a stream will not be used for transfer of data.
+const TInt KTextDataLength = 200;
+
+// max column size
+const TInt KMaxColLength = 1000;
+
+// Buffer size to cause HDbsBuf::DoReadL() ipc check to be executed
+const TInt KBufSizeDoReadL = 1000;
+
+// Buffer size to cause HDbsBuf::UnderflowL() ipc check to be executed
+const TInt KBufSizeUnderflowL = 500;
+
+class Defect_071149
+	{
+public:
+	static void TestL();
+	static const TDesC& Name();
+	};
+
+
+const TDesC& Defect_071149::Name()
+	{
+	_LIT(KName,"071149");
+	return KName;
+	}
+
+/**
+HDbsBuf did not handle case when iIpc.iHandle is 0 causing IPC calls to panic.
+The handle is 0 when opening a stream and all data is retrieved in this request.
+
+@SYMTestCaseID			SYSLIB-DBMS-CT-1491
+@SYMTestCaseDesc		Tests for defect number 590829
+@SYMTestPriority			High
+@SYMTestActions			Tests by setting up failure conditions.
+@SYMTestExpectedResults	Test must not fail
+@SYMDEF				INC071149
+*/
+void Defect_071149::TestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-1491 "));
+	Print(_S("Creating test database"));
+
+	// Connect to dbms and open db
+	RDbs dbs;
+	RDbNamedDatabase db;
+	test2 (db.Replace(TheFs,KTestDatabase),KErrNone);
+	db.Close();
+
+	test2(dbs.Connect(), KErrNone);
+	test2(db.Open(dbs,KTestDatabase), KErrNone);
+
+	// creating column to hold LongText
+	CDbColSet *colSet = CDbColSet::NewL();
+	CleanupStack::PushL(colSet);
+	colSet->AddL(TDbCol(_L("Id"), EDbColLongText, KMaxColLength));
+
+	// create table
+	test2(db.CreateTable(KTableA, *colSet), KErrNone);
+	CleanupStack::PopAndDestroy(colSet);
+
+	// create text data to add to table
+	HBufC* testText = HBufC::New(KTextDataLength);
+	test(testText !=NULL );
+	TPtr ptr = testText->Des();
+	for(TInt y=0;y<KTextDataLength;++y)
+		{
+		ptr.Append(TChar('A'));
+		}
+
+	// add data to table
+	RDbTable newTable;
+	test2 (newTable.Open(db,KTableA),KErrNone);
+	db.Begin();
+	newTable.InsertL();
+	newTable.SetColL(1, ptr);
+	newTable.PutL();
+
+	test2 (db.Commit(),KErrNone);
+	test2 (newTable.CountL(), 1);
+	newTable.Close();
+
+	// cleanup
+	delete testText;
+
+	// disconnect from db and dbms
+	db.Close();
+	dbs.Close();
+
+//
+	// Connect to dbms and open db
+	test2(dbs.Connect(), KErrNone);
+	test2(db.Open(dbs,KTestDatabase), KErrNone);
+
+	// Test handle check in HDbsBuf::DoReadL() - See defect
+	// If the handle check did not exist in the production code then
+	// it would panic.
+
+	// create test table
+	RDbTable testTable;
+	test2 (testTable.Open(db,KTableA),KErrNone);
+	db.Begin();
+	testTable.FirstL();
+	testTable.GetL();
+
+	// Open stream
+	RDbColReadStream rs;
+    	rs.OpenLC( testTable, 1);
+
+	// Read data
+	TBuf<KBufSizeDoReadL> buf;
+	TRAPD(err, rs.ReadL( buf, buf.MaxLength()));
+	if(err != KErrNone)
+		{
+		test2(err, KErrEof);
+		}
+	CleanupStack::PopAndDestroy();  // Close rs
+	testTable.Close();
+
+//
+	// Test handle check in HDbsBuf::UnderflowL() - additional error not in defect
+	// If the handle check did not exist in the production code then
+	// it would panic.
+
+	// create test table
+	test2 (testTable.Open(db,KTableA),KErrNone);
+	testTable.NextL();
+	testTable.GetL();
+
+	// Open stream
+	RDbColReadStream rs2;
+    	rs2.OpenLC( testTable, 1);
+
+	// Read data
+	TBuf<KBufSizeUnderflowL> buf2;
+	TRAP(err, rs2.ReadL( buf2, buf2.MaxLength()));
+	if(err != KErrNone)
+		{
+		test2(err, KErrEof);
+		}
+	CleanupStack::PopAndDestroy();  // Close rs
+
+	// tidy up
+	testTable.Close();
+	db.Close();
+	dbs.Close();
+	}
+
+/////////////////////////////////////////////////
+
+/**
+Cached, unused tables were breaking the iterator in CDbTableDatabase::CheckIdle
+The latter function has been re-written to restart the iteration when tables are Idle()'d
+
+@SYMTestCaseID          SYSLIB-DBMS-CT-0582
+@SYMTestCaseDesc        Tests for defect number 590829
+@SYMTestPriority        Medium
+@SYMTestActions        	Tests by setting up failure conditions.
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+void Defect_590829::TestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0582 "));
+	Print(_S("Creating test database"));
+	test2 (TheDatabase.Replace(TheFs,KTestDatabase),KErrNone);
+	TheDatabase.Begin();
+	test2 (TheDatabase.Execute(_L("create table A (id counter)")),KErrNone);
+	test2 (TheDatabase.Execute(_L("create table B (id counter)")),KErrNone);
+	test2 (TheDatabase.Execute(_L("create table C (id counter)")),KErrNone);
+	test2 (TheDatabase.Commit(),KErrNone);
+//
+	Print(_S("Setting up failure"));
+	RDbTable tA,tB,tC;
+	test2 (tA.Open(TheDatabase,KTableA),KErrNone);
+	test2 (tB.Open(TheDatabase,KTableB),KErrNone);
+	tB.Close();
+	test2 (tC.Open(TheDatabase,KTableC),KErrNone);
+	tC.Close();
+	TheDatabase.Begin();
+	tA.Close();
+//
+	Print(_S("Testing fix"));
+	test2 (TheDatabase.Commit(),KErrNone);
+	TheDatabase.Destroy();
+	}
+
+/////////////////////////////////////////////////
+
+class Defect_394751
+	{
+public:
+	static void TestL();
+	static const TDesC& Name();
+private:
+	static TInt Thread(TAny*);
+	static void ThreadL();
+	};
+
+
+const TDesC& Defect_394751::Name()
+	{
+	_LIT(KName,"394751");
+	return KName;
+	}
+
+void Defect_394751::ThreadL()
+	{
+	RDbs dbs;
+	RDbNamedDatabase db;
+	User::LeaveIfError(dbs.Connect());
+	User::LeaveIfError(db.Open(dbs,KTestDatabase));
+	db.Begin();
+	db.Begin();	/// panic now
+	User::Panic(_L("T_BUG failure"),0);
+	}
+
+TInt Defect_394751::Thread(TAny*)
+	{
+	User::SetJustInTime(EFalse);	// disable debugger panic handling
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	if (!cleanup)
+		return KErrNoMemory;
+	TRAPD(r,ThreadL());
+	delete cleanup;
+	return r;
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0583
+@SYMTestCaseDesc        Tests for defect number 394751
+@SYMTestPriority        Medium
+@SYMTestActions        	Tests for thread exit status.
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+void Defect_394751::TestL()
+//
+//
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0583 "));
+	Print(_S("Creating test database"));
+	test2 (TheDatabase.Replace(TheFs,KTestDatabase),KErrNone);
+	TheDatabase.Close();
+//
+	RDbs dbs;
+	test2 (dbs.Connect(),KErrNone);
+//
+	Print(_S("Running test thread"));
+	RThread t;
+	_LIT(KTestThread,"Defect Fix 394751");
+	test2 (t.Create(KTestThread,&Thread,0x2000,0x1000,0x10000,0,EOwnerThread),KErrNone);
+	TRequestStatus s;
+	t.Logon(s);
+	test2 (s.Int(),KRequestPending);
+	t.Resume();
+	Print(_S("Awaiting completion"));
+	User::WaitForRequest(s);
+	_LIT(KCategory,"DBMS-Table");
+	test2 (t.ExitType(),EExitPanic);
+	test (t.ExitCategory()==KCategory);
+	test2 (t.ExitReason(),11);		// begin nested transaction
+	User::SetJustInTime(ETrue);	// enable debugger panic handling
+	t.Close();
+//
+	test2 (dbs.ResourceCount(),0);
+	dbs.Close();
+	}
+
+///////////////////////////////////////////////////////////
+
+class Defect_COMBBAR_463J5D
+	{
+public:
+	static void TestL();
+	static const TDesC& Name();
+private:
+	static void WaitForServerExit();
+	static TInt Thread(TAny*);
+	};
+
+const TDesC& Defect_COMBBAR_463J5D::Name()
+	{
+	_LIT(KName,"COMBBAR_463J5D");
+	return KName;
+	}
+
+void Defect_COMBBAR_463J5D::WaitForServerExit()
+	{
+	_LIT(KDbmsServer,"*!DBMS server");
+	TFullName n;
+	TFindThread ft(KDbmsServer);
+	if (ft.Next(n)==KErrNone)
+		{
+		RThread t;
+		if (t.Open(ft)==KErrNone)
+			{
+			TRequestStatus s;
+			t.Logon(s);
+			User::WaitForRequest(s);
+			t.Close();
+			}
+		}
+	}
+
+TInt Defect_COMBBAR_463J5D::Thread(TAny*)
+//
+// Just try to start the server
+//
+	{
+	RDbs dbs;
+	return dbs.Connect();
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0584
+@SYMTestCaseDesc        Tests for defect number COMBBAR_463J5D
+@SYMTestPriority        Medium
+@SYMTestActions        	Testing that defect COMBBAR_463J5D in ER5 Defects database has been fixed
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+void Defect_COMBBAR_463J5D::TestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0584 "));
+	Print(_S("Wait for the server to exit"));
+	WaitForServerExit();
+//
+	Print(_S("Create the launching threads"));
+	RThread t1,t2;
+	TRequestStatus s1,s2;
+	_LIT(KThread1,"t1");
+	test2 (t1.Create(KThread1,&Thread,0x2000,0,0,EOwnerThread),KErrNone);
+	t1.SetPriority(EPriorityLess);
+	t1.Logon(s1);
+	_LIT(KThread2,"t2");
+	test2 (t2.Create(KThread2,&Thread,0x2000,0,0,EOwnerThread),KErrNone);
+	t2.SetPriority(EPriorityLess);
+	t2.Logon(s2);
+//
+	Print(_S("Run the threads and wait"));
+	t1.Resume();
+	t2.Resume();
+	User::WaitForRequest(s1,s2);
+	if (s1==KRequestPending)
+		User::WaitForRequest(s1);
+	else
+		User::WaitForRequest(s2);
+//
+	test2 (t1.ExitType(),EExitKill);
+	if (s1.Int()!=KErrNotFound)
+		test2 (s1.Int(),KErrNone);
+	test2 (t2.ExitType(),EExitKill);
+	if (s2.Int()!=KErrNotFound)
+		test2 (s2.Int(),KErrNone);
+	t1.Close();
+	t2.Close();
+	}
+
+/////////////////////////////////////////////////////////
+
+class Defect_EDNATHE_48AEZW
+	{
+public:
+	static void TestL();
+	static const TDesC& Name();
+	};
+
+const TDesC& Defect_EDNATHE_48AEZW::Name()
+	{
+	_LIT(KName,"EDNATHE_48AEZW");
+	return KName;
+	}
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0585
+@SYMTestCaseDesc        Tests for defect number EDNATHE_48AEZW
+@SYMTestPriority        Medium
+@SYMTestActions        	Tests for navigation and deletion
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+void Defect_EDNATHE_48AEZW::TestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0585 "));
+	Print(_S("Set up database"));
+	test2 (TheDatabase.Replace(TheFs,KTestDatabase),KErrNone);
+	test2 (TheDatabase.Begin(),KErrNone);
+	test2 (TheDatabase.Execute(_L("create table A (id counter)")),KErrNone);
+	RDbView v1;
+	test2 (v1.Prepare(TheDatabase,_L("select * from A"),v1.EInsertOnly),KErrNone);
+	test2 (v1.EvaluateAll(),KErrNone);
+	for (TInt ii=0;ii<4;++ii)
+		{
+		v1.InsertL();
+		v1.PutL();
+		}
+	test2 (TheDatabase.Commit(),KErrNone);
+	v1.Close();
+//
+	Print(_S("test navigation"));
+	test2 (v1.Prepare(TheDatabase,_L("select * from A where id=0")),KErrNone);
+	test2 (v1.EvaluateAll(),KErrNone);
+	v1.FirstL();
+	RDbView v2;
+	test2 (v2.Prepare(TheDatabase,_L("select * from A where id=1")),KErrNone);
+	test2 (v2.EvaluateAll(),KErrNone);
+	v2.FirstL();
+	v2.DeleteL();
+	TRAPD(r, v1.NextL());
+	test2 (r,KErrNone);
+	test (v1.AtEnd());
+	v2.Close();
+//
+	Print(_S("test deletion"));
+	v1.FirstL();
+	test2 (v2.Prepare(TheDatabase,_L("select * from A where id=2")),KErrNone);
+	test2 (v2.EvaluateAll(),KErrNone);
+	v2.FirstL();
+	v2.DeleteL();
+	TRAP(r,v1.DeleteL());
+	test2 (r,KErrNone);
+	TRAP(r, v1.NextL());
+	test2 (r,KErrNone);
+	test (v1.AtEnd());
+//
+	v1.Close();
+	v2.Close();
+	TheDatabase.Close();
+	}
+
+/////////////////////////////////////////////////////////
+
+static void NextTest(const TDesC& aName)
+	{
+	TBuf<80> buf;
+	buf=_S("Checking Defect ");
+	buf+=aName;
+	test.Next(buf);
+	}
+
+template <typename T>
+struct RunTest
+	{
+	RunTest()
+		{
+		const TDesC& name = T::Name();
+		NextTest(name);
+		TRAPD(r,T::TestL());
+		test2 (r,KErrNone);
+		Print(_S("Defect fixed"));
+		}
+	};
+
+LOCAL_C void setupTestDirectory()
+//
+// Prepare the test directory.
+//
+    {
+	TInt r=TheFs.Connect();
+	test(r==KErrNone);
+//
+	r=TheFs.MkDir(KTestDatabase);
+	test(r==KErrNone || r==KErrAlreadyExists);
+	}
+
+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 DeleteDataFile(const TDesC& aFullName)
+	{
+	RFs fsSession;
+	TInt err = fsSession.Connect();
+	if(err == KErrNone)
+		{
+		TEntry entry;
+		if(fsSession.Entry(aFullName, entry) == KErrNone)
+			{
+			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
+			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
+			if(err != KErrNone)
+				{
+				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
+				}
+			err = fsSession.Delete(aFullName);
+			if(err != KErrNone)
+				{
+				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
+				}
+			}
+		fsSession.Close();
+		}
+	else
+		{
+		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
+		}
+	}
+
+GLDEF_C TInt E32Main()
+//
+// Test streaming conversions.
+//
+    {
+	__UHEAP_MARK;
+	test.Title();
+	setupTestDirectory();
+	setupCleanup();
+//
+	test.Start(_L("Verifying defect fixes"));
+	RunTest<Defect_COMBBAR_463J5D>();
+// The following short delay is needed for ccover builds only.
+// Without the pause, the kernel scheduler would intermittently
+// crash 0.3s after the last test ended.
+	User::After(500000);
+	test.Printf(_L("Resume test after delay.\n"));
+
+	RunTest<Defect_394751>();
+	User::After(500000);
+	test.Printf(_L("Resume test after delay.\n"));
+
+	RunTest<Defect_590829>();
+	User::After(500000);
+	test.Printf(_L("Resume test after delay.\n"));
+
+	RunTest<Defect_071149>();
+	User::After(500000);
+	test.Printf(_L("Resume test after delay.\n"));
+
+	RunTest<Defect_EDNATHE_48AEZW>();
+
+	// clean up data files used by this test - must be done before call to End() - DEF047652
+	::DeleteDataFile(KTestDatabase);
+
+	test.End();
+//
+	delete TheTrapCleanup;
+
+	TheFs.Close();
+	test.Close();
+	__UHEAP_MARKEND;
+	return 0;
+    }