persistentstorage/sql/TEST/t_sqloom3.cpp
changeset 0 08ec8eefde2f
child 13 211563e4b919
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/TEST/t_sqloom3.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,401 @@
+// Copyright (c) 2005-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 "t_sqloom.h"
+
+RTest TheTest(_L("t_sqloom3 test"));
+
+///////////////////////////////////////////////////////////////////////////////////////
+///////////////         RSqlDatabase OOM tests         ////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+
+/**
+@SYMTestCaseID			SYSLIB-SQL-CT-1615, SYSLIB-SQL-CT-1639
+@SYMTestCaseDesc		RSqlDatabase::Create() OOM test - secure and non-secure databases.
+						Precondition: the database does not exist.
+						The test calls RSqlDatabase::Create() while simulating OOM failures and checks
+						that there are no memory and resource leaks.
+						Note: It's possible for a database to be created even after memory allocation
+						has failed. This is because SQLITE reuses some pages of the page cache which
+						have been allocated but are curently not in use. This means it is necessary
+						to delete the database and continue checking for memory and resource leaks
+						even after a database has been created successfully.
+@SYMTestPriority		High
+@SYMTestActions			RSqlDatabase::Create() OOM test
+@SYMTestExpectedResults Test must not fail
+@SYMREQ					REQ5792
+                        REQ5793
+                        REQ10271
+                        REQ10273
+                        REQ10274
+*/
+void DoCreateDatabaseOomTest(const TDesC& aDbFileName, TDbType aDbType, TInt aExpectedError, const TDesC8* aConfigStr = NULL)
+	{
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1639 RSqlDatabase::Create() - OOM test"));
+	RSqlSecurityPolicy securityPolicy;
+	CreateTestSecurityPolicy(securityPolicy);
+	enum TMethodType {ENonLeavingMethod, ELeavingMethod};
+	const TMethodType KMethodType[] = {ENonLeavingMethod, ELeavingMethod};
+	for(TInt j=0;j<sizeof(KMethodType)/sizeof(KMethodType[0]);++j)
+		{
+		for(TInt i=0;i<(TInt)(sizeof(TheOomTestType)/sizeof(TheOomTestType[0]));++i)
+			{
+			if(aExpectedError != KErrAlreadyExists)
+				{
+				(void)RSqlDatabase::Delete(aDbFileName);
+				}
+			TInt err = KErrNone;
+			TInt failingAllocationNo = 0;
+			TInt allocationNo = 0;
+			TInt maxAllocationNo = TheOomTestType[i] == EServerSideTest ? KDoCreateDatabaseOomTestAllocLimitServer : KDoCreateDatabaseOomTestAllocLimitClient;
+			while(allocationNo < maxAllocationNo)
+				{
+				MarkHandles();
+				MarkAllocatedCells();
+
+				__UHEAP_MARK;
+
+				RSqlDatabase db;
+
+				SetDbHeapFailure(TheOomTestType[i], ++allocationNo);
+
+				if(KMethodType[j] == ENonLeavingMethod)
+					{
+					err =  aDbType == ESecureDb ? db.Create(aDbFileName, securityPolicy, aConfigStr) : db.Create(aDbFileName, aConfigStr);
+					}
+				else
+					{
+					TRAP(err, aDbType == ESecureDb ? db.CreateL(aDbFileName, securityPolicy, aConfigStr) : db.CreateL(aDbFileName, aConfigStr));
+					}
+
+				db.Close();
+				if(err != KErrNoMemory)
+					{
+					TEST2(err, aExpectedError);
+					}
+				else
+					{
+					failingAllocationNo = allocationNo;
+					}
+
+				ResetDbHeapFailure(TheOomTestType[i]);
+
+				if(err == KErrNone && aExpectedError != KErrAlreadyExists)
+					{
+					err = db.Delete(aDbFileName);
+					TEST2(err, KErrNone);
+					}
+
+				__UHEAP_MARKEND;
+
+				CheckAllocatedCells();
+				CheckHandles();
+				}
+			TEST2(err, aExpectedError);
+			PrintEndOfOomTest(TheOomTestType[i], failingAllocationNo + 1);
+			}
+		}
+	RSqlDatabase::Delete(aDbFileName);
+	securityPolicy.Close();
+	}
+
+//"RSqlDatabase::Open()" OOM test
+void OpenDatabaseL(RSqlDatabase& aDb, const TDesC& aDbFileName, TDbType)
+	{
+	TInt err = aDb.Open(aDbFileName);
+	User::LeaveIfError(err);
+	}
+
+//"RSqlDatabase::Exec()" OOM test (8-bit SQL statements), syntax error
+void ExecBadStatement8L(RSqlDatabase& aDb, const TDesC&, TDbType)
+	{
+	_LIT8(KSqlString, "CREATE TABL BBB(Fld1 INTEGER, Fld2 BIGINT, Fld3 DOUBLE, Fld4 TEXT)");
+	TInt err = aDb.Exec(KSqlString);
+	User::LeaveIfError(err);
+	}
+
+//"RSqlDatabase::Exec()" OOM test (16-bit SQL statements), syntax error
+void ExecBadStatement16L(RSqlDatabase& aDb, const TDesC&, TDbType)
+	{
+	_LIT(KSqlString, "CREATE TABLE B!B!B(Fld1 INTEGER, Fld2 BIGINT, Fld3 DOUBLE, Fld4 TEXT)");
+	TInt err = aDb.Exec(KSqlString);
+	User::LeaveIfError(err);
+	}
+
+/**
+@SYMTestCaseID			SYSLIB-SQL-CT-1813
+@SYMTestCaseDesc		RSqlDatabase methods - negative OOM test
+						Precondition: the database exists.
+						The test calls the given as an argument function while simulating OOM failures
+						and checks that there are no memory and resource leaks. The calling function is expected to fail
+						with aExpectedError error.
+@SYMTestPriority		High
+@SYMTestActions			RSqlDatabase methods - negative OOM tests
+@SYMTestExpectedResults Test must not fail
+@SYMREQ					REQ5792
+                        REQ5793
+*/
+void DoDbOomNegativeTest(TDbFuncPtrL aTestFunctionPtrL, const TDesC& aDbFileName, TDbAction aDbAction, TInt aExpectedError)
+	{
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-1813 RSqlDatabase - negative OOM test"));
+	for(TInt i=0;i<(TInt)(sizeof(TheOomTestType)/sizeof(TheOomTestType[0]));++i)
+		{
+		TInt err = KErrNoMemory;
+		TInt failingAllocationNo = 0;
+		while(err == KErrNoMemory)
+			{
+			MarkHandles();
+			MarkAllocatedCells();
+
+			__UHEAP_MARK;
+
+			if(TheOomTestType[i] == EServerSideTest)
+				{//If aDbAction is EOpenDb, then we will delay the heap failure simulation, until the database is opened
+				SetDbHeapFailure(TheOomTestType[i], ++failingAllocationNo, aDbAction == EOpenDb);
+				}
+
+			RSqlDatabase db;
+			//if aDbAction is EOpenDb then this is a OOM test different than a test for RSqlDatabase::Open
+			if(aDbAction == EOpenDb)
+				{
+				err = db.Open(aDbFileName);
+				TEST2(err, KErrNone);
+				}
+
+			if(TheOomTestType[i] == EClientSideTest)
+				{
+				SetDbHeapFailure(TheOomTestType[i], ++failingAllocationNo);
+				}
+
+			TRAP(err, (*aTestFunctionPtrL)(db, aDbFileName, ENonSecureDb));
+			db.Close();
+			if(err != KErrNoMemory)
+				{
+				TEST2(err, aExpectedError);
+				}
+
+			ResetDbHeapFailure(TheOomTestType[i]);
+
+			__UHEAP_MARKEND;
+
+			CheckAllocatedCells();
+			CheckHandles();
+			}
+		TEST2(err, aExpectedError);
+		PrintEndOfOomTest(TheOomTestType[i], failingAllocationNo);
+		}
+	RSqlDatabase::Delete(aDbFileName);
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+
+//RSqlDatabase - negative OOM tests
+void DbOomNegativeTestsL()
+	{
+	TheTest.Printf(_L("===RSqlDatabase::Open(), non-existing drive\r\n"));
+	_LIT(KDbName1, "A:[1111CCCC]db1.db");
+	DoDbOomNegativeTest(&OpenDatabaseL, KDbName1, ENotOpenDb, KErrNotReady);
+
+	TheTest.Printf(_L("===RSqlDatabase::Open(), non-existing file\r\n"));
+	_LIT(KDbName2, "c:\\test\\nofile.db");
+	DoDbOomNegativeTest(&OpenDatabaseL, KDbName2, ENotOpenDb, KErrNotFound);
+
+	TheTest.Printf(_L("===RSqlDatabase::Open(), zero-length name\r\n"));
+	_LIT(KDbName3, "");
+	DoDbOomNegativeTest(&OpenDatabaseL, KDbName3, ENotOpenDb, KErrBadName);
+
+	TheTest.Printf(_L("===RSqlDatabase::Open(), directory name\r\n"));
+	_LIT(KDbName4, "C:\\TEST\\");
+	DoDbOomNegativeTest(&OpenDatabaseL, KDbName4, ENotOpenDb, KErrBadName);
+
+	TheTest.Printf(_L("===RSqlDatabase::Create(), secure database already exists\r\n"));
+	RSqlSecurityPolicy securityPolicy;
+	CreateTestSecurityPolicy(securityPolicy);
+	RSqlDatabase db;
+	TInt err = db.Create(KSecureDb2, securityPolicy);
+	TEST2(err, KErrNone);
+	db.Close();
+	securityPolicy.Close();
+	DoCreateDatabaseOomTest(KSecureDb2, ESecureDb, KErrAlreadyExists);
+
+	TheTest.Printf(_L("===RSqlDatabase::Create(), database already exists\r\n"));
+	err = db.Create(KTestDb2);
+	TEST2(err, KErrNone);
+	db.Close();
+	DoCreateDatabaseOomTest(KTestDb2, ENonSecureDb, KErrAlreadyExists);
+
+	TheTest.Printf(_L("===RSqlDatabase::Exec(), 8-bit SQL, syntax error\r\n"));
+	err = db.Create(KTestDb);
+	TEST2(err, KErrNone);
+	db.Close();
+	DoDbOomNegativeTest(&ExecBadStatement8L, KTestDb, EOpenDb, KSqlErrGeneral);
+
+	TheTest.Printf(_L("===RSqlDatabase::Exec(), 16-bit SQL, syntax error\r\n"));
+	err = db.Create(KTestDb);
+	TEST2(err, KErrNone);
+	db.Close();
+	DoDbOomNegativeTest(&ExecBadStatement16L, KTestDb, EOpenDb, KSqlErrGeneral);
+	}
+
+void DEF114297PrepareStmtL(RSqlDatabase& aDb, RSqlStatement& aStmt)
+	{
+	_LIT(KSelectSql, "SELECT e.* FROM edge AS e, node AS n1, node AS n2 WHERE n1.name = 'alice' AND n2.name = 'bob' AND e.orig = n1.id AND e.dest = n2.id ORDER BY n2.name DESC");
+	TInt err = aStmt.Prepare(aDb, KSelectSql);
+	User::LeaveIfError(err);
+	}
+
+/**
+@SYMTestCaseID			SYSLIB-SQL-UT-4004
+@SYMTestCaseDesc		Test for DEF114297 - SqlSrv.EXE::!SQL Server OOM Test for PrepareL.
+						The test does an OOM test for RSqlStatement::Prepare() using a specific SELECT SQL statement.
+@SYMTestPriority		High
+@SYMTestActions			Test for DEF114297 - SqlSrv.EXE::!SQL Server OOM Test for PrepareL.
+@SYMTestExpectedResults Test must not fail
+@SYMDEF					DEF114297
+*/
+void DEF114297()
+	{
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4004  ===DEF114297 - SqlSrv.EXE::!SQL Server OOM Test for PrepareL "));
+	(void)RSqlDatabase::Delete(KTestDb);
+	RSqlDatabase db;
+	TInt err = db.Create(KTestDb);
+	TEST2(err, KErrNone);
+	err = db.Exec(_L("CREATE TABLE node(id INTEGER PRIMARY KEY,name TEXT)"));
+	TEST2(err, 1);
+	err = db.Exec(_L("CREATE INDEX node_idx ON node(name)"));
+	TEST2(err, 1);
+	err = db.Exec(_L("CREATE TABLE edge(orig INTEGER REFERENCES node,dest INTEGER REFERENCES node,PRIMARY KEY(orig, dest))"));
+	TEST2(err, 1);
+	err = db.Exec(_L("CREATE INDEX edge_idx ON edge(dest,orig)"));
+	TEST2(err, 1);
+	err = db.Exec(_L("INSERT INTO node(id,name) VALUES(1,'alice')"));
+	TEST2(err, 1);
+	err = db.Exec(_L("INSERT INTO node(id,name) VALUES(2,'bob')"));
+	TEST2(err, 1);
+	err = KErrNoMemory;
+	TInt failingAllocationNo = 0;
+	while(err == KErrNoMemory)
+		{
+		MarkHandles();
+		MarkAllocatedCells();
+
+		__UHEAP_MARK;
+
+		SetHeapFailure(EServerSideTest, ++failingAllocationNo);
+
+    	RSqlStatement stmt;
+		TRAP(err, DEF114297PrepareStmtL(db, stmt));
+		stmt.Close();
+		if(err != KErrNoMemory)
+			{
+			TEST2(err, KErrNone);
+			}
+
+		ResetHeapFailure(EServerSideTest);
+
+		__UHEAP_MARKEND;
+
+		CheckAllocatedCells();
+		CheckHandles();
+		}
+	db.Close();
+	(void)RSqlDatabase::Delete(KTestDb);
+	}
+
+/**
+@SYMTestCaseID			SYSLIB-SQL-UT-4011
+@SYMTestCaseDesc		Test for DEF115815 - SELECT random()&1==-1 causes sql server to crash.
+						The test does an OOM test for RSqlStatement::Prepare() using a specific SELECT SQL statement.
+@SYMTestPriority		High
+@SYMTestActions			Test for DEF115815 - SELECT random()&1==-1 causes sql server to crash.
+@SYMTestExpectedResults Test must not fail
+@SYMDEF					DEF115815
+*/
+void DEF115815()
+	{
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4011 ===DEF115815 - SELECT random()&1==-1 causes sql server to crash "));
+	(void)RSqlDatabase::Delete(KTestDb);
+	RSqlDatabase db;
+	TInt err = db.Create(KTestDb);
+	TEST2(err, KErrNone);
+	err = db.Exec(_L("CREATE TABLE node(id INTEGER)"));
+	TEST2(err, 1);
+	err = KErrNoMemory;
+	TInt failingAllocationNo = 0;
+	while(err == KErrNoMemory)
+		{
+		MarkHandles();
+		MarkAllocatedCells();
+
+		__UHEAP_MARK;
+
+		SetHeapFailure(EServerSideTest, ++failingAllocationNo);
+
+    	RSqlStatement stmt;
+		err = stmt.Prepare(db, _L("SELECT random()&1==-1"));
+		stmt.Close();
+		if(err != KErrNoMemory)
+			{
+			TEST2(err, KErrNone);
+			}
+
+		ResetHeapFailure(EServerSideTest);
+
+		__UHEAP_MARKEND;
+
+		CheckAllocatedCells();
+		CheckHandles();
+		}
+	db.Close();
+	(void)RSqlDatabase::Delete(KTestDb);
+	}
+
+void DoTestsL()
+	{
+	TheTest.Start(_L("SQL OOM-3 tests"));
+
+	DbOomNegativeTestsL();
+
+	DEF114297();
+
+	DEF115815();
+	}
+
+TInt E32Main()
+	{
+	TheTest.Title();
+
+	CTrapCleanup* tc = CTrapCleanup::New();
+
+	__UHEAP_MARK;
+
+	CreateTestDir();
+	DeleteTestFiles();
+
+	TRAPD(err, DoTestsL());
+	DeleteTestFiles();
+	TEST2(err, KErrNone);
+
+	__UHEAP_MARKEND;
+
+	TheTest.End();
+	TheTest.Close();
+
+	delete tc;
+
+	User::Heap().Check();
+	return KErrNone;
+	}