diff -r 31a8f755b7fe -r 211563e4b919 persistentstorage/sql/TEST/t_sqloom6.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/sql/TEST/t_sqloom6.cpp Wed Apr 14 17:46:32 2010 +0300 @@ -0,0 +1,733 @@ +// Copyright (c) 2010 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 +#include +#include "SqlResourceTester.h" //TSqlResourceTester +#include "sqlite3.h" +#include "SqliteSymbian.h" + +//In order to be able to compile the test, the following variables are defined (used inside the OS porting layer, +//when _SQLPROFILER macro is defined) +#ifdef _SQLPROFILER +TInt TheSqlSrvProfilerFileRead = 0; +TInt TheSqlSrvProfilerFileWrite = 0; +TInt TheSqlSrvProfilerFileSync = 0; +TInt TheSqlSrvProfilerFileSetSize = 0; +#endif + +/////////////////////////////////////////////////////////////////////////////////////// + +RTest TheTest(_L("t_sqloom6 test")); + +_LIT(KTestDir, "c:\\test\\"); +_LIT(KDbFile, "c:\\test\\t_sqloom6.db"); + +static RSqlDatabase TheDb; +static RSqlStatement TheStmt; + +static TInt TheProcessHandleCount = 0; +static TInt TheThreadHandleCount = 0; +static TInt TheAllocatedCellsCount = 0; + +/////////////////////////////////////////////////////////////////////////////////////// + +void DestroyTestEnv() + { + TheStmt.Close(); + TheDb.Close(); + (void)RSqlDatabase::Delete(KDbFile); + sqlite3SymbianLibFinalize(); + CloseSTDLIB(); + } + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +//Test macros and functions +void Check(TInt aValue, TInt aLine) + { + if(!aValue) + { + DestroyTestEnv(); + RDebug::Print(_L("*** Expresssion evaluated to false\r\n")); + TheTest(EFalse, aLine); + } + } +void Check(TInt aValue, TInt aExpected, TInt aLine) + { + if(aValue != aExpected) + { + DestroyTestEnv(); + RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue); + TheTest(EFalse, aLine); + } + } +#define TEST(arg) ::Check((arg), __LINE__) +#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__) + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static void MarkHandles() + { + RThread().HandleCount(TheProcessHandleCount, TheThreadHandleCount); + } + +static void MarkAllocatedCells() + { + TheAllocatedCellsCount = User::CountAllocCells(); + } + +static void CheckAllocatedCells() + { + TInt allocatedCellsCount = User::CountAllocCells(); + TEST2(allocatedCellsCount, TheAllocatedCellsCount); + } + +static void CheckHandles() + { + TInt endProcessHandleCount; + TInt endThreadHandleCount; + + RThread().HandleCount(endProcessHandleCount, endThreadHandleCount); + + TEST2(TheProcessHandleCount, endProcessHandleCount); + TEST2(TheThreadHandleCount, endThreadHandleCount); + } + +static void OomPreStep(TInt aFailingAllocationNo) + { + MarkHandles(); + MarkAllocatedCells(); + __UHEAP_MARK; + TSqlResourceTester::Mark(); + TSqlResourceTester::SetHeapFailure(RHeap::EBurstFailNext, aFailingAllocationNo); + } + +static void OomPostStep() + { + __UHEAP_RESET; + TSqlResourceTester::SetHeapFailure(RHeap::ENone, 0); + TSqlResourceTester::Check(); + CheckAllocatedCells(); + CheckHandles(); + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CreateTestEnv() + { + RFs fs; + TInt err = fs.Connect(); + TEST2(err, KErrNone); + + err = fs.MkDir(KTestDir); + TEST(err == KErrNone || err == KErrAlreadyExists); + + err = fs.CreatePrivatePath(EDriveC); + TEST(err == KErrNone || err == KErrAlreadyExists); + + fs.Close(); + + sqlite3SymbianLibInit(); + } + +//Creates a UTF8 encoded database with: +// - One table with three colums: A(ColumnName1234567890, Col2, Col3); +// - One record in the table with values: ('A1234567890', 'A12345', ''); +void CreateTestDb(const TDesC& aDbName) + { + TBuf8<100> dbName8; + dbName8.Copy(aDbName); + sqlite3* db = 0; + int rc = sqlite3_open((const char*)dbName8.PtrZ(), &db); + TEST2(rc, SQLITE_OK); + rc = sqlite3_exec(db, "CREATE TABLE A(ColumnName1234567890 TEXT, Col2 LONG TEXT, Col3 SMALL TEXT)", 0, 0, 0); + TEST2(rc, SQLITE_OK); + rc = sqlite3_exec(db, "INSERT INTO A VALUES('A1234567890', 'A12345', '')", 0, 0, 0); + TEST2(rc, SQLITE_OK); + sqlite3_close(db); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4176 +@SYMTestCaseDesc RSqlStatement::ColumnName() OOM test. +@SYMTestPriority High +@SYMTestActions The test runs RSqlStatement::ColumnName() in an OOM simulation loop. + The difference betwee this test case and the similar test case in t_sqloom2 is that here: + - burst OOM simulation is used; + - UTF8 encoded database is used; + - only SQL server side OOM simulation is performed; + The purpose of the test is to verify that the ColumnName() call behaves correctly + when the related sqlite3_column_name16() call performed by the SQL server fails + with "no memory". +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF145033 +*/ +void ColumnNameOomTest() + { + //This is not really a full OOM test, because the SQL server counts only the number of active statement and + //stream objects, the allocated memory cells are not counted. + //The reason that the allocated memory cells are not counted, and in case of an OOM failure - checked, is + //because the SQL server can make some per-connection memory allocations (cache pages, etc.) + //and they will not be deallocated when the statement object is closed. + //But the result of the RSqlStatement::ColumnName() operation is checked. If there is a failed memory + //allocation on the server side, the returned column name can be NULL and that will be tested. + + (void)RSqlDatabase::Delete(KDbFile); + + TheTest.Printf(_L("Iteration:\r\n")); + + CreateTestDb(KDbFile);//Creates UTF8 encoded database with one table with one record. + + TInt err = TheDb.Open(KDbFile); + TEST2(err, KErrNone); + + TInt failingAllocationNo = 0; + err = KErrNoMemory; + while(err == KErrNoMemory) + { + TheTest.Printf(_L(" %d"), ++failingAllocationNo); + OomPreStep(failingAllocationNo); + + err = TheStmt.Prepare(TheDb, _L("SELECT * FROM A")); + if(err != KErrNone) + { + goto LabelOomPostStep; + } + + TPtrC name; + err = TheStmt.ColumnName(0, name); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(name == _L("ColumnName1234567890")); + + err = TheStmt.ColumnName(1, name); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(name == _L("Col2")); + + err = TheStmt.ColumnName(2, name); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(name == _L("Col3")); + +LabelStmtClose: + TheStmt.Close(); + +LabelOomPostStep: + OomPostStep(); + } + + TheDb.Close(); + (void)RSqlDatabase::Delete(KDbFile); + + TEST2(err, KErrNone); + TheTest.Printf(_L("\r\n===RSqlStatement::ColumnName() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4177 +@SYMTestCaseDesc RSqlStatement::ParameterName() OOM test. +@SYMTestPriority High +@SYMTestActions The test runs RSqlStatement::ParameterName() in an OOM simulation loop. + The difference betwee this test case and the similar test case in t_sqloom2 is that here: + - burst OOM simulation is used; + - UTF8 encoded database is used; + - only SQL server side OOM simulation is performed; + The purpose of the test is to verify that the ParameterName() call behaves correctly + if the related sqlite3_bind_parameter_name() call performed by the SQL server fails + with "no memory". +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF145033 +*/ +void ParameterNameOomTest() + { + //This is not really a full OOM test, because the SQL server counts only the number of active statement and + //stream objects, the allocated memory cells are not counted. + //The reason that the allocated memory cells are not counted, and in case of an OOM failure - checked, is + //because the SQL server can make some per-connection memory allocations (cache pages, etc.) + //and they will not be deallocated when the statement object is closed. + //But the result of the RSqlStatement::ParameterName() operation is checked. If there is a failed memory + //allocation on the server side, the returned column name can be NULL and that will be tested. + + (void)RSqlDatabase::Delete(KDbFile); + + TheTest.Printf(_L("Iteration:\r\n")); + + CreateTestDb(KDbFile);//Creates UTF8 encoded database with one table with one record. + + TInt err = TheDb.Open(KDbFile); + TEST2(err, KErrNone); + + TInt failingAllocationNo = 0; + err = KErrNoMemory; + while(err == KErrNoMemory) + { + TheTest.Printf(_L(" %d"), ++failingAllocationNo); + OomPreStep(failingAllocationNo); + + err = TheStmt.Prepare(TheDb, _L("SELECT * FROM A WHERE Col2 != :Prm1234567890 AND Col3 != :Prm2 AND ColumnName1234567890 != ?")); + if(err != KErrNone) + { + goto LabelOomPostStep; + } + + TPtrC name; + err = TheStmt.ParameterName(0, name); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(name == _L(":Prm1234567890")); + + err = TheStmt.ParameterName(1, name); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(name == _L(":Prm2")); + + err = TheStmt.ParameterName(2, name); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(name == _L("?2")); + +LabelStmtClose: + TheStmt.Close(); + +LabelOomPostStep: + OomPostStep(); + } + + TheDb.Close(); + (void)RSqlDatabase::Delete(KDbFile); + + TEST2(err, KErrNone); + TheTest.Printf(_L("\r\n===RSqlStatement::ColumnName() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4178 +@SYMTestCaseDesc RSqlStatement::ColumnText() OOM test. +@SYMTestPriority High +@SYMTestActions The test runs RSqlStatement::ColumnText() in an OOM simulation loop. + The difference betwee this test case and the similar test case in t_sqloom2 is that here: + - burst OOM simulation is used; + - UTF8 encoded database is used; + - only SQL server side OOM simulation is performed; + The purpose of the test is to verify that the ColumnText() call behaves correctly + when the related sqlite3_column_text16() call performed by the SQL server fails + with "no memory" (or the sqlite3_column_bytes16() call). +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF145033 +*/ +void ColumnTextOomTest() + { + //This is not really a full OOM test, because the SQL server counts only the number of active statement and + //stream objects, the allocated memory cells are not counted. + //The reason that the allocated memory cells are not counted, and in case of an OOM failure - checked, is + //because the SQL server can make some per-connection memory allocations (cache pages, etc.) + //and they will not be deallocated when the statement object is closed. + //But the result of the RSqlStatement::ColumnText() operation is checked. If there is a failed memory + //allocation on the server side, the returned column name can be NULL and that will be tested. + + (void)RSqlDatabase::Delete(KDbFile); + + TheTest.Printf(_L("Iteration:\r\n")); + + CreateTestDb(KDbFile);//Creates UTF8 encoded database with one table with one record. + + TInt err = TheDb.Open(KDbFile); + TEST2(err, KErrNone); + + TInt failingAllocationNo = 0; + err = KErrNoMemory; + while(err == KErrNoMemory) + { + TheTest.Printf(_L(" %d"), ++failingAllocationNo); + OomPreStep(failingAllocationNo); + + err = TheStmt.Prepare(TheDb, _L("SELECT * FROM A")); + if(err != KErrNone) + { + goto LabelOomPostStep; + } + err = TheStmt.Next(); + if(err != KSqlAtRow) + { + goto LabelStmtClose; + } + + TPtrC data; + err = TheStmt.ColumnText(0, data); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(data == _L("A1234567890")); + + err = TheStmt.ColumnText(1, data); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(data == _L("A12345")); + + err = TheStmt.ColumnText(2, data); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST(data == _L("")); + +LabelStmtClose: + TheStmt.Close(); + +LabelOomPostStep: + OomPostStep(); + } + + TheDb.Close(); + (void)RSqlDatabase::Delete(KDbFile); + + TEST2(err, KErrNone); + TheTest.Printf(_L("\r\n===RSqlStatement::ColumnText() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4179 +@SYMTestCaseDesc RSqlColumnReadStream OOM test. +@SYMTestPriority High +@SYMTestActions The test runs RSqlColumnReadStream in an OOM simulation loop. + The difference betwee this test case and the similar test case in t_sqloom2 is that here: + - burst OOM simulation is used; + - UTF8 encoded database is used; + - only SQL server side OOM simulation is performed; + The purpose of the test is to verify that the RSqlColumnReadStream APIs behave correctly + when the related sqlite3_column_text16() call performed by the SQL server fails + with "no memory" (or the sqlite3_column_bytes16() call). +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF145033 +*/ +void TextColumnReadStreamOomTest() + { + //This is not really a full OOM test, because the SQL server counts only the number of active statement and + //stream objects, the allocated memory cells are not counted. + //The reason that the allocated memory cells are not counted, and in case of an OOM failure - checked, is + //because the SQL server can make some per-connection memory allocations (cache pages, etc.) + //and they will not be deallocated when the statement object is closed. + //But the result of the RSqlColumnReadStream::ReadL() operation is checked. If there is a failed memory + //allocation on the server side, the returned column name can be NULL and that will be tested. + + (void)RSqlDatabase::Delete(KDbFile); + + TheTest.Printf(_L("Iteration:\r\n")); + + CreateTestDb(KDbFile);//Creates UTF8 encoded database with one table with one record. + + TInt err = TheDb.Open(KDbFile); + TEST2(err, KErrNone); + + TInt failingAllocationNo = 0; + err = KErrNoMemory; + while(err == KErrNoMemory) + { + TheTest.Printf(_L(" %d"), ++failingAllocationNo); + OomPreStep(failingAllocationNo); + + err = TheStmt.Prepare(TheDb, _L("SELECT * FROM A")); + if(err != KErrNone) + { + goto LabelOomPostStep; + } + err = TheStmt.Next(); + if(err != KSqlAtRow) + { + goto LabelCloseStmt; + } + + RSqlColumnReadStream strm; + err = strm.ColumnText(TheStmt, 0); + if(err != KErrNone) + { + goto LabelCloseStmt; + } + TBuf<50> data; + TRAP(err, strm.ReadL(data, 11)); + strm.Close(); + if(err != KErrNone) + { + goto LabelCloseStmt; + } + TEST(data == _L("A1234567890")); + + err = strm.ColumnText(TheStmt, 1); + if(err != KErrNone) + { + goto LabelCloseStmt; + } + TRAP(err, strm.ReadL(data, 6)); + strm.Close(); + if(err != KErrNone) + { + goto LabelCloseStmt; + } + TEST(data == _L("A12345")); + + err = strm.ColumnText(TheStmt, 2); + if(err != KErrNone) + { + goto LabelCloseStmt; + } + TInt len = -1; + TRAP(err, len = strm.Source()->SizeL());//The column value is with 0 length + strm.Close(); + if(err != KErrNone) + { + goto LabelCloseStmt; + } + TEST2(len, 0); + +LabelCloseStmt: + TheStmt.Close(); + +LabelOomPostStep: + OomPostStep(); + } + + TheDb.Close(); + (void)RSqlDatabase::Delete(KDbFile); + + TEST2(err, KErrNone); + TheTest.Printf(_L("\r\n===RSqlColumnReadStream OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4180 +@SYMTestCaseDesc TSqlScalarFullSelectQuery::SelectTextL() OOM test. +@SYMTestPriority High +@SYMTestActions The test runs TSqlScalarFullSelectQuery::SelectTextL() in an OOM simulation loop. + The difference betwee this test case and the similar test case in t_sqloom2 is that here: + - burst OOM simulation is used; + - UTF8 encoded database is used; + - only SQL server side OOM simulation is performed; + The purpose of the test is to verify that the SelectTextL() call behaves correctly + when the related sqlite3_column_text16() call performed by the SQL server fails + with "no memory" (or the sqlite3_column_bytes16() call). +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF145033 +*/ +void ScalarColumnTextOomTest() + { + //This is not really a full OOM test, because the SQL server counts only the number of active statement and + //stream objects, the allocated memory cells are not counted. + //The reason that the allocated memory cells are not counted, and in case of an OOM failure - checked, is + //because the SQL server can make some per-connection memory allocations (cache pages, etc.) + //and they will not be deallocated when the statement object is closed. + //But the result of the TSqlScalarFullSelectQuery::SelectTextL() operation is checked. If there is a failed memory + //allocation on the server side, the returned column name can be NULL and that will be tested. + + (void)RSqlDatabase::Delete(KDbFile); + + TheTest.Printf(_L("Iteration:\r\n")); + + CreateTestDb(KDbFile);//Creates UTF8 encoded database with one table with one record. + + TInt err = TheDb.Open(KDbFile); + TEST2(err, KErrNone); + + TInt failingAllocationNo = 0; + err = KErrNoMemory; + while(err == KErrNoMemory) + { + TheTest.Printf(_L(" %d"), ++failingAllocationNo); + OomPreStep(failingAllocationNo); + + TSqlScalarFullSelectQuery query(TheDb); + TBuf<50> data; + TRAP(err, query.SelectTextL(_L("SELECT ColumnName1234567890 FROM A"), data)); + if(err != KErrNone) + { + goto LabelOomPostStep; + } + TEST(data == _L("A1234567890")); + + TRAP(err, query.SelectTextL(_L("SELECT Col2 FROM A"), data)); + if(err != KErrNone) + { + goto LabelOomPostStep; + } + TEST(data == _L("A12345")); + + TRAP(err, query.SelectTextL(_L("SELECT Col3 FROM A"), data)); + if(err != KErrNone) + { + goto LabelOomPostStep; + } + TEST(data == _L("")); + +LabelOomPostStep: + OomPostStep(); + } + + TheDb.Close(); + (void)RSqlDatabase::Delete(KDbFile); + + TEST2(err, KErrNone); + TheTest.Printf(_L("\r\n===TSqlScalarFullSelectQuery::SelectTextL() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4181 +@SYMTestCaseDesc RSqlStatement::DeclaredColumnType() OOM test. +@SYMTestPriority High +@SYMTestActions The test runs RSqlStatement::DeclaredColumnType() in an OOM simulation loop. + The difference betwee this test case and the similar test case in t_sqloom2 is that here: + - burst OOM simulation is used; + - UTF8 encoded database is used; + - only SQL server side OOM simulation is performed; + The purpose of the test is to verify that the DeclaredColumnType() call behaves correctly + when the related sqlite3_column_name16() call performed by the SQL server fails + with "no memory". +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF145033 +*/ +void DeclaredColumnTypeOomTest() + { + //This is not really a full OOM test, because the SQL server counts only the number of active statement and + //stream objects, the allocated memory cells are not counted. + //The reason that the allocated memory cells are not counted, and in case of an OOM failure - checked, is + //because the SQL server can make some per-connection memory allocations (cache pages, etc.) + //and they will not be deallocated when the statement object is closed. + //But the result of the RSqlStatement::DeclaredColumnType() operation is checked. If there is a failed memory + //allocation on the server side, the returned column name can be NULL and that will be tested. + + (void)RSqlDatabase::Delete(KDbFile); + + TheTest.Printf(_L("Iteration:\r\n")); + + CreateTestDb(KDbFile);//Creates UTF8 encoded database with one table with one record. + + TInt err = TheDb.Open(KDbFile); + TEST2(err, KErrNone); + + TInt failingAllocationNo = 0; + err = KErrNoMemory; + while(err == KErrNoMemory) + { + TheTest.Printf(_L(" %d"), ++failingAllocationNo); + OomPreStep(failingAllocationNo); + + err = TheStmt.Prepare(TheDb, _L("SELECT * FROM A")); + if(err != KErrNone) + { + goto LabelOomPostStep; + } + + TSqlColumnType colType = ESqlNull; + err = TheStmt.DeclaredColumnType(0, colType); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST2(colType, ESqlText); + + colType = ESqlNull; + err = TheStmt.DeclaredColumnType(1, colType); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST2(colType, ESqlText); + + colType = ESqlNull; + err = TheStmt.DeclaredColumnType(2, colType); + if(err != KErrNone) + { + goto LabelStmtClose; + } + TEST2(colType, ESqlText); + +LabelStmtClose: + TheStmt.Close(); + +LabelOomPostStep: + OomPostStep(); + } + + TheDb.Close(); + (void)RSqlDatabase::Delete(KDbFile); + + TEST2(err, KErrNone); + TheTest.Printf(_L("\r\n===RSqlStatement::DeclaredColumnType() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo); + } + +void DoTests() + { + TheTest.Start(_L(" @SYMTestCaseID:PDS-SQL-CT-4176 RSqlStatement::ColumnName() OOM test")); + ColumnNameOomTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4177 RSqlStatement::ParameterName() OOM test")); + ParameterNameOomTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4178 RSqlStatement::ColumnText() OOM test")); + ColumnTextOomTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4179 RSqlColumnReadStream OOM test")); + TextColumnReadStreamOomTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4180 TSqlScalarFullSelectQuery::SelectTextL() OOM test")); + ScalarColumnTextOomTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4181 RSqlStatement::DeclaredColumnType() OOM test")); + DeclaredColumnTypeOomTest(); + } + +TInt E32Main() + { + TheTest.Title(); + + CTrapCleanup* tc = CTrapCleanup::New(); + TheTest(tc != NULL); + + __UHEAP_MARK; + + CreateTestEnv(); + DoTests(); + DestroyTestEnv(); + + __UHEAP_MARKEND; + + TheTest.End(); + TheTest.Close(); + + delete tc; + + User::Heap().Check(); + return KErrNone; + }