diff -r 000000000000 -r bde4ae8d615e os/persistentdata/persistentstorage/sql/TEST/t_sqlapi2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/persistentdata/persistentstorage/sql/TEST/t_sqlapi2.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,1849 @@ +// Copyright (c) 2007-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 //MStreamBuf +#include +#include "SqlResourceProfiler.h" + +/////////////////////////////////////////////////////////////////////////////////////// + +RTest TheTest(_L("t_sqlapi2 test")); +RSqlDatabase TheDb; +RSqlStatement TheStmt; + +_LIT(KTestDir, "c:\\test\\"); +_LIT(KTestDbName1, "c:\\test\\t_sqlapi2_1.db"); +_LIT(KTestDbName2, "c:\\private\\1111C1EF\\t_sqlapi2_2.db");//t_sqlapi2 app - private database + +_LIT(KDbInjectedName1, "DELETE FROM symbian_settings;c:\\test\\A.db"); +_LIT(KDbInjectedName2, "c:\\test\\A.db;DELETE FROM symbian_settings;"); + +const TInt KBufLen = 8192; +TBuf TheBuf; + +/////////////////////////////////////////////////////////////////////////////////////// + +void DeleteTestFiles() + { + TheStmt.Close(); + TheDb.Close(); + (void)RSqlDatabase::Delete(KDbInjectedName2); + (void)RSqlDatabase::Delete(KDbInjectedName1); + (void)RSqlDatabase::Delete(KTestDbName2); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +//Test macros and functions +void Check(TInt aValue, TInt aLine) + { + if(!aValue) + { + DeleteTestFiles(); + TheTest(EFalse, aLine); + } + } +void Check(TInt aValue, TInt aExpected, TInt aLine) + { + if(aValue != aExpected) + { + DeleteTestFiles(); + 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__) + +/////////////////////////////////////////////////////////////////////////////////////// + +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(); + } + +/////////////////////////////////////////////////////////////////////////////////////// + +/** +@SYMTestCaseID SYSLIB-SQL-UT-3512 +@SYMTestCaseDesc RSqlStatement::ColumnCount() - SELECT statements test + The test creates a database with a table and then checks the ColumnCount() + return result for the following statements: + - select all columns; + - select a subset; + - select an expression; + - select a constant; + - multi-table select; + - select a function; + - select plus sub-query; +@SYMTestPriority High +@SYMTestActions RSqlStatement::ColumnCount() test +@SYMTestExpectedResults Test must not fail +@SYMREQ REQ8035 +*/ +void ColumnCountTest() + { + + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + //Create table 1 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT,Id2 INTEGER,Data BLOB)")); + TEST(err >= 0); + + err = TheDb.Exec(_L("INSERT INTO A VALUES(1,'AAA',6234567890,x'11AAFD0C771188')")); + TEST2(err, 1); + + //Select all columns (SELECT *) + err = TheStmt.Prepare(TheDb, _L("SELECT * FROM A")); + TEST2(err, KErrNone); + TInt cnt = TheStmt.ColumnCount(); + TEST2(cnt, 4); + TheStmt.Close(); + //Select all columns (SELECT a,b,c...) + err = TheStmt.Prepare(TheDb, _L("SELECT Id,Name,Id2,Data FROM A")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 4); + TheStmt.Close(); + //Select column subset + err = TheStmt.Prepare(TheDb, _L("SELECT Id,Name,Data FROM A")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 3); + TheStmt.Close(); + //Select column subset + expression + err = TheStmt.Prepare(TheDb, _L("SELECT Id,Id+Id2 FROM A")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 2); + TheStmt.Close(); + //Select column subset + constant + err = TheStmt.Prepare(TheDb, _L("SELECT Id,Id2,345.78 FROM A")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 3); + TheStmt.Close(); + //Select SQL function + err = TheStmt.Prepare(TheDb, _L("SELECT COUNT(*) FROM A")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 1); + TheStmt.Close(); + //Create table 2 + err = TheDb.Exec(_L("CREATE TABLE B(Id INTEGER, S INTEGER)")); + TEST(err >= 0); + err = TheDb.Exec(_L("INSERT INTO B VALUES(1,25)")); + TEST2(err, 1); + //Multitable select + err = TheStmt.Prepare(TheDb, _L("SELECT A.Id,B.S FROM A,B WHERE A.Id = B.Id")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 2); + TheStmt.Close(); + //Select + Subquery + err = TheStmt.Prepare(TheDb, _L("SELECT Id FROM A WHERE (SELECT S FROM B WHERE A.Id = B.Id) > 10")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 1); + TheStmt.Close(); + //Cleanup + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-3513 +@SYMTestCaseDesc RSqlStatement::ColumnCount() - DDL and DML statements test + The test creates a database with a table and then checks the ColumnCount() return result for + DML statements (INSERT/UPDATE/DELETE) and DDL statements (CREATE TABLE/INDEX, DROP TABLE?INDEX). + The column count for DML and DDL statements should be 0. +@SYMTestPriority High +@SYMTestActions RSqlStatement::ColumnCount() test +@SYMTestExpectedResults Test must not fail +@SYMREQ REQ8035 +*/ +void ColumnCountTest2() + { + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + //Create table + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT,Id2 INTEGER,Data BLOB)")); + TEST(err >= 0); + err = TheDb.Exec(_L("INSERT INTO A VALUES(1,'AAA',6234567890,x'11AAFD0C771188')")); + TEST2(err, 1); + //INSERT statement + err = TheStmt.Prepare(TheDb, _L("INSERT INTO A(Id,Id2) VALUES(:P1,:P2)")); + TEST2(err, KErrNone); + TInt cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + TheStmt.Close(); + //UPDATE statement + err = TheStmt.Prepare(TheDb, _L("UPDATE A SET Id2=100 WHERE Id=:P1")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + TheStmt.Close(); + //DELETE statement + err = TheStmt.Prepare(TheDb, _L("DELETE FROM A WHERE Id=:P1")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + TheStmt.Close(); + //CREATE TABLE statement + err = TheStmt.Prepare(TheDb, _L("CREATE TABLE B AS SELECT * FROM A")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + TheStmt.Close(); + //DROP TABLE statement + err = TheStmt.Prepare(TheDb, _L("DROP TABLE A")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + TheStmt.Close(); + //CREATE INDEX statement + err = TheStmt.Prepare(TheDb, _L("CREATE INDEX I ON A(Id)")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + err = TheStmt.Exec(); + TEST(err >= 0); + TheStmt.Close(); + //DROP INDEX statement + err = TheStmt.Prepare(TheDb, _L("DROP INDEX I")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + TheStmt.Close(); + //CREATE TRIGGER statement + err = TheStmt.Prepare(TheDb, + _L("CREATE TRIGGER Trg BEFORE DELETE ON A \ + BEGIN \ + SELECT CASE WHEN ((SELECT Id2 FROM A WHERE A.Id = old.Id) > 0) \ + THEN RAISE (ABORT, 'Id2 > 0') \ + END;\ + END;")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + TheStmt.Close(); + //CREATE VIEW statement + err = TheStmt.Prepare(TheDb, _L("CREATE VIEW V AS SELECT * FROM A")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + err = TheStmt.Exec(); + TEST(err >= 0); + TheStmt.Close(); + //DROP VIEW statement + err = TheStmt.Prepare(TheDb, _L("DROP VIEW V")); + TEST2(err, KErrNone); + cnt = TheStmt.ColumnCount(); + TEST2(cnt, 0); + TheStmt.Close(); + //Cleanup + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-3514 +@SYMTestCaseDesc RSqlStatement::DeclaredColumnType() test + The test creates a database with a table and then checks the DeclaredColumnType() return result for: + - select all column from the table and check their types; + - multi-table select plus column type checks; + - select expression - the expected column type is ESqlInt; + - select constant - the expected column type is ESqlInt; +@SYMTestPriority High +@SYMTestActions RSqlStatement::ColumnCount() test +@SYMTestExpectedResults Test must not fail +@SYMREQ REQ8035 +*/ +void DeclaredColumnTypeTest() + { + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + const char* KColTypeNames[] = + {"INTEGER", "LONG INTEGER", "INT", "SHORT INT", "SMALL INT", "TINY INT", "SHORT", "INT64", + "TEXT", "LONGTEXT", "CLOB", "CHAR", "CHARACTER(20)", "LONG TEXT", + "BINARY", "LONG BINARY", "LONGBINARY", "BLOB", "LONGBLOB", "LONG BLOB", + "REAL", "FLOAT", "DOUBLE", "LONG DOUBLE", + "LONG LONG", "BOO HOO"}; + const TSqlColumnType KColTypes[] = + {ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt, + ESqlText,ESqlText,ESqlText,ESqlText,ESqlText,ESqlText, + ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary, + ESqlReal,ESqlReal,ESqlReal,ESqlReal, + ESqlInt,ESqlInt}; + const TInt KColTypeCnt = sizeof(KColTypes) / sizeof(KColTypes[0]); + TEST2(sizeof(KColTypeNames) / sizeof(KColTypeNames[0]), KColTypeCnt); + //Create table 1 + TBuf8<512> sql; + sql.Copy(_L8("CREATE TABLE T(")); + for(TInt i=0;i= 0); + //Select all columns (SELECT *) + err = TheStmt.Prepare(TheDb, _L("SELECT * FROM T")); + TEST2(err, KErrNone); + TInt cnt = TheStmt.ColumnCount(); + TEST2(cnt, KColTypeCnt); + TSqlColumnType colType; + for(TInt i=0;i= 0); + //Multi-table select + err = TheStmt.Prepare(TheDb, _L("SELECT T.A1,T2.Id,T.A9,T2.Data FROM T,T2")); + TEST2(err, KErrNone); + err = TheStmt.DeclaredColumnType(0, colType); + TEST2(err, KErrNone); + TEST2(colType, ESqlInt); + err = TheStmt.DeclaredColumnType(1, colType); + TEST2(err, KErrNone); + TEST2(colType, ESqlInt); + err = TheStmt.DeclaredColumnType(2, colType); + TEST2(err, KErrNone); + TEST2(colType, ESqlText); + err = TheStmt.DeclaredColumnType(3, colType); + TEST2(err, KErrNone); + TEST2(colType, ESqlBinary); + TheStmt.Close(); + //Select expression + err = TheStmt.Prepare(TheDb, _L("SELECT (Id + Data) AS RES FROM t2")); + TEST2(err, KErrNone); + err = TheStmt.DeclaredColumnType(0, colType); + TEST2(err, KErrNone); + TEST2(colType, ESqlInt); + TheStmt.Close(); + //Select constant + err = TheStmt.Prepare(TheDb, _L("SELECT (Id + Data) AS RES, 55.89 FROM t2")); + TEST2(err, KErrNone); + err = TheStmt.DeclaredColumnType(1, colType); + TEST2(err, KErrNone); + TEST2(colType, ESqlInt); + TheStmt.Close(); + //Cleanup + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4017 +@SYMTestCaseDesc RSqlStatement::ColumnName(TInt, TPtrC&) test + The test creates a database with a table and then checks the ColumnName() return result for: + - select all column from the table and check their names; + - multi-table select plus column name checks; + - select expression - the expected column name is RES + - select constant - the expected column type is 55.89 +@SYMTestPriority High +@SYMTestActions RSqlStatement::ColumnName() test +@SYMTestExpectedResults Test must not fail +@SYMCR RMAD-7B7EV5 + Add SQL Server APIs to retrieve column and parameter names +*/ +void ColumnNameTest() + { + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + const char* KColTypeNames[] = + {"INTEGER", "LONG INTEGER", "INT", "SHORT INT", "SMALL INT", "TINY INT", "SHORT", "INT64", + "TEXT", "LONGTEXT", "CLOB", "CHAR", "CHARACTER(20)", "LONG TEXT", + "BINARY", "LONG BINARY", "LONGBINARY", "BLOB", "LONGBLOB", "LONG BLOB", + "REAL", "FLOAT", "DOUBLE", "LONG DOUBLE", + "LONG LONG", "BOO HOO"}; + const TSqlColumnType KColTypes[] = + {ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt,ESqlInt, + ESqlText,ESqlText,ESqlText,ESqlText,ESqlText,ESqlText, + ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary,ESqlBinary, + ESqlReal,ESqlReal,ESqlReal,ESqlReal, + ESqlInt,ESqlInt}; + const TInt KColTypeCnt = sizeof(KColTypes) / sizeof(KColTypes[0]); + TEST2(sizeof(KColTypeNames) / sizeof(KColTypeNames[0]), KColTypeCnt); + //Create table 1 + TBuf8<512> sql; + sql.Copy(_L8("CREATE TABLE T(")); + for(TInt i=0;i= 0); + //Select all columns (SELECT *) + err = TheStmt.Prepare(TheDb, _L("SELECT * FROM T")); + TEST2(err, KErrNone); + TInt cnt = TheStmt.ColumnCount(); + TEST2(cnt, KColTypeCnt); + TPtrC colName; + TBuf<128> expectedColName; + for(TInt i=0;i= 0); + //Multi-table select + err = TheStmt.Prepare(TheDb, _L("SELECT T.A1,T2.Id,T.A9,T2.DATA FROM T,T2")); + TEST2(err, KErrNone); + err = TheStmt.ColumnName(0, colName); + TEST2(err, KErrNone); + TEST2(colName.Compare(_L("A1")), 0); + err = TheStmt.ColumnName(1, colName); + TEST2(err, KErrNone); + TEST2(colName.Compare(_L("Id")), 0); + err = TheStmt.ColumnName(2, colName); + TEST2(err, KErrNone); + TEST2(colName.Compare(_L("A9")), 0); + err = TheStmt.ColumnName(3, colName); + TEST2(err, KErrNone); + TEST2(colName.Compare(_L("DATA")), 0); + TheStmt.Close(); + //Select expression + err = TheStmt.Prepare(TheDb, _L("SELECT (Id + Data) AS RES FROM t2")); + TEST2(err, KErrNone); + err = TheStmt.ColumnName(0, colName); + TEST2(err, KErrNone); + TEST2(colName.Compare(_L("RES")), 0); + //Too big column index + err = TheStmt.ColumnName(1323, colName); + TEST2(err, KErrNotFound); + //Negative column index + err = TheStmt.ColumnName(-100, colName); + TEST2(err, KErrNotFound); + TheStmt.Close(); + //Select constant + err = TheStmt.Prepare(TheDb, _L("SELECT (Id + Data) AS RES, 55.89 FROM t2")); + TEST2(err, KErrNone); + err = TheStmt.ColumnName(1, colName); + TEST2(err, KErrNone); + TEST2(colName.Compare(_L("55.89")), 0); + TheStmt.Close(); + //Cleanup + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4018 +@SYMTestCaseDesc RSqlStatement::ParameterName(TInt, TPtrC&) and RSqlStatement::ParamName(TInt, TPtrC&) test + DML test: + The test creates a database with a table and prepares an insert query. + The test then checks the ParameterName() and ParamName() return result for: + - Named parameters - return the named param + - Unnamed parameters - return ? +@SYMTestPriority High +@SYMTestActions RSqlStatement::ParameterName() and RSqlStatement::ParamName() test +@SYMTestExpectedResults Test must not fail +@SYMCR RMAD-7B7EV5 + Add SQL Server APIs to retrieve column and parameter names +*/ +void ParamNameTest() + { + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + const char* KColTypeNames[] = + {"INTEGER", "TEXT"}; + const TInt KColTypeCnt = sizeof(KColTypeNames) / sizeof(KColTypeNames[0]); + //Create table 1 + TBuf8<256> sql; + sql.Copy(_L8("CREATE TABLE T(")); + for(TInt i=0;i= 0); + TheStmt.Close(); + + // Create insert statement, then check param names + err = TheStmt.Prepare(TheDb, _L("INSERT INTO T (A1, A2) VALUES (:prm1, :prm2)")); + TEST2(err, KErrNone); + TPtrC paramName; + TBuf<128> expectedParamName; + for(TInt i=0;i= 0); + err = db1.Exec(_L("INSERT INTO A VALUES(2)")); + TEST2(err, 1); + err = db2.Open(KTestDbName1); + TEST2(err, KErrNone); + err = db1.Exec(_L("COMMIT TRANSACTION")); + TEST(err >= 0); + db2.Close(); + db1.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +TInt StackOverflowThreadFunc(void* aData) + { + CTrapCleanup* tc = CTrapCleanup::New(); + TEST(tc != NULL); + + User::SetJustInTime(EFalse); // disable debugger panic handling + + TInt* cntptr = reinterpret_cast (aData); + TEST(cntptr != NULL); + TInt cnt = *cntptr; + + HBufC* buf = HBufC::New(cnt * 12 + 32);//enough for the "SELECT Id FROM A WHERE Id=v1 OR Id=v2 OR ..." string + if(!buf) + { + delete tc; + return KErrNoMemory; + } + TPtr sql = buf->Des(); + + TInt err = TheDb.Open(KTestDbName1); + if(err != KErrNone) + { + delete buf; + delete tc; + return err; + } + + TTime now; + now.UniversalTime(); + TInt64 seed = now.Int64(); + + sql.Copy(_L("SELECT Id FROM A WHERE ")); + for(TInt i=0;i 0) + { + TInt count = next; + TheTest.Printf(_L("'OR' expr. count: %d\r\n"), count); + RThread thread; + _LIT(KThreadName,"ORThread"); //stack minheap maxheap + err = thread.Create(KThreadName, &StackOverflowThreadFunc, 0x2000, 0x00100000, 0x02000000, &count); + TEST2(err, KErrNone); + + TRequestStatus status; + thread.Logon(status); + TEST2(status.Int(), KRequestPending); + thread.Resume(); + User::WaitForRequest(status); + User::SetJustInTime(ETrue); // enable debugger panic handling + + TInt exitType = thread.ExitType(); + const TDesC& exitCategory = thread.ExitCategory(); + TInt exitReason = thread.ExitReason(); + TheTest.Printf(_L("Exit type: %d, exit reason: %d, exit category: %S\r\n"), exitType, exitReason, &exitCategory); + thread.Close(); + TEST(exitReason != KErrServerTerminated); + TEST(exitType != EExitPanic); + + TInt tmp = next; + if(status.Int() != KErrNone) + {//The number of the OR subexpressions is too big and cannot be parsed. Decrease the number, repeat the test. + next -= Abs(next - prev) / 2; + } + else + {//KErrNone: The number of the OR subexpressions has been successfully parsed. Increase the number, repeat the test. + next += Abs(next - prev) / 2; + } + prev = tmp; + } + TheTest.Printf(_L("The test has succeeded with an expression with %d ORs\r\n"), prev); + } + +void AssertSettingsTable() + { + TSqlScalarFullSelectQuery query(TheDb); + TInt recCount = 0; + TRAPD(err, recCount = query.SelectIntL(_L("SELECT COUNT(*) FROM symbian_settings"))); + TEST2(err, KErrNone); + TEST2(recCount, 1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4086 +@SYMTestCaseDesc RSqlBlobWriteStream::OpenL() and RSqlBlobReadStream::OpenL() - injection test + The test attempts to open a blob stream with an attached database name containing + "DELETE FROM symbian_settings" statement. The test should not delete the content of the + "symbian_settings" table. + The test also attempts to open a blob stream with a set of very long database/table/column names. +@SYMTestPriority Medium +@SYMTestActions RSqlBlobWriteStream::OpenL() and RSqlBlobReadStream::OpenL() - injection test +@SYMTestExpectedResults Test must not fail +@SYMREQ REQ5792 + REQ10410 + REQ10411 + REQ10418 +*/ +void BlobStreamInjectionTest() + { + (void)RSqlDatabase::Delete(KTestDbName1); + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Data BLOB)")); + TEST2(err, 1); + err = TheDb.Exec(_L("INSERT INTO A VALUES(1, x'11223344556677889900')")); + TEST2(err, 1); + _LIT(KAttachDb, "AttachDb"); + err = TheDb.Attach(KTestDbName1, KAttachDb); + TEST2(err, KErrNone); + //RSqlBlobWriteStream::OpenL() - attached database name injected + RSqlBlobWriteStream strm1; + TRAP(err, strm1.OpenL(TheDb, _L("A"), _L("Data"), 1, _L("Id;DELETE FROM symbian_settings;"))); + TEST(err != KErrNone); + AssertSettingsTable(); + //RSqlBlobReadStream::OpenL() - attached database name injected + RSqlBlobReadStream strm2; + TRAP(err, strm2.OpenL(TheDb, _L("A"), _L("Data"), 1, _L("Id;DELETE FROM symbian_settings;"))); + TEST(err != KErrNone); + AssertSettingsTable(); + //Attempt to open a write blob stream with a set of very long database/table/column names. + TBuf longName; + longName.SetLength(longName.MaxLength()); + RSqlBlobWriteStream strm3; + TRAP(err, strm3.OpenL(TheDb, longName, longName, 1, longName)); + TEST(err != KErrNone); + //Attempt to open a read blob stream with a set of very long database/table/column names. + RSqlBlobReadStream strm4; + TRAP(err, strm4.OpenL(TheDb, longName, longName, 1, longName)); + TEST(err != KErrNone); + //Attempt to open a write blob stream with a set of KNullDesC database/table/column names. + RSqlBlobWriteStream strm5; + TRAP(err, strm5.OpenL(TheDb, KNullDesC, KNullDesC, 1, KNullDesC)); + TEST(err != KErrNone); + //Attempt to open a read blob stream with a set of KNullDesC database/table/column names. + RSqlBlobReadStream strm6; + TRAP(err, strm6.OpenL(TheDb, KNullDesC, KNullDesC, 1, KNullDesC)); + TEST(err != KErrNone); + //Attempt to open a read blob stream, where the blob column name is invalid and contains non-convertible characters. + TBuf<3> invName; + invName.SetLength(3); + invName[0] = TChar(0xD800); + invName[1] = TChar(0xFC00); + invName[2] = TChar(0x0000); + RSqlBlobReadStream strm7; + TRAP(err, strm7.OpenL(TheDb, _L("A"), invName, 1, KNullDesC)); + TEST(err != KErrNone); + //Attempt to open a read blob stream, where the table name is invalid and contains non-convertible characters. + RSqlBlobReadStream strm8; + TRAP(err, strm8.OpenL(TheDb, invName, _L("Data"), 1, KNullDesC)); + TEST(err != KErrNone); + //Attempt to open a read blob stream, where the attached db name is invalid and contains non-convertible characters. + RSqlBlobReadStream strm9; + TRAP(err, strm9.OpenL(TheDb, _L("A"), _L("Data"), 1, invName)); + TEST(err != KErrNone); + // + err = TheDb.Detach(KAttachDb); + TEST2(err, KErrNone); + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4087 +@SYMTestCaseDesc Bound parameter values test. + The test verifies that bound parameters with big text/binary values retain their values after + the RSqlStatement::Reset() call. The old bound paramegter values can be used for the next + RSqlStatement::Exec() call. +@SYMTestActions Bound parameter values test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +@SYMREQ REQ5792 +*/ +void BoundParameterValuesTest() + { + (void)RSqlDatabase::Delete(KTestDbName1); + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)")); + TEST2(err, 1); + err = TheDb.Exec(_L("CREATE TABLE A2(T1 TEXT, T2 TEXT)")); + TEST2(err, 1); + + RSqlStatement stmt1, stmt2; + err = stmt1.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)")); + TEST2(err, KErrNone); + err = stmt2.Prepare(TheDb, _L("INSERT INTO A2 VALUES(:Prm1, :Prm2)")); + TEST2(err, KErrNone); + //Insert 1 record into table "A1". T2 = "ZZZZ.....". + TheBuf.SetLength(KBufLen - 100); + TheBuf.Fill(TChar('Z')); + err = stmt1.BindText(0, TheBuf); + TEST2(err, KErrNone); + err = stmt1.BindText(1, TheBuf); + TEST2(err, KErrNone); + err = stmt1.Exec(); + TEST2(err, 1); + err = stmt1.Reset(); + TEST2(err, KErrNone); + //Insert 1 record into table "A2". T2 = "AAAAAAA.....". + TheBuf.SetLength(KBufLen); + TheBuf.Fill(TChar('A')); + err = stmt2.BindText(0, TheBuf); + TEST2(err, KErrNone); + err = stmt2.BindText(1, TheBuf); + TEST2(err, KErrNone); + err = stmt2.Exec(); + TEST2(err, 1); + err = stmt2.Reset(); + TEST2(err, KErrNone); + //Insert 1 record into table "A1". T2 not set. T2 should be initialized with the previous bound value - "ZZZZZZ....". + //If the problem is not fixed, the SQLITE will attempt to access an already deleted region of memory. + TheBuf.SetLength(KBufLen - 100); + TheBuf.Fill(TChar('B')); + err = stmt1.BindText(0, TheBuf); + TEST2(err, KErrNone); + err = stmt1.Exec(); + TEST2(err, 1); + err = stmt1.Reset(); + TEST2(err, KErrNone); + + stmt2.Close(); + stmt1.Close(); + + //Check the inserted records. + TSqlScalarFullSelectQuery q(TheDb); + TRAP(err, q.SelectTextL(_L("SELECT T2 FROM A1 WHERE ROWID=1"), TheBuf)); + TEST2(err, KErrNone); + TEST2(TheBuf.Length(), (KBufLen - 100)); + for(TInt i1=0;i1<(KBufLen - 100);++i1) + { + TEST2(TheBuf[i1], TChar('Z')); + } + TRAP(err, q.SelectTextL(_L("SELECT T2 FROM A1 WHERE ROWID=2"), TheBuf)); + TEST2(err, KErrNone); + TEST2(TheBuf.Length(), (KBufLen - 100)); + for(TInt i2=0;i2<(KBufLen - 100);++i2) + { + TEST2(TheBuf[i2], TChar('Z')); + } + + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4076 +@SYMTestCaseDesc Bound parameter values test. + The test verifies that when a RSqlParamWriteStream object is used for binding parameter values, + it is safe to erverse the order of RSqlParamWriteStream::Close() and RSqlStatement::Close() calls. +@SYMTestActions Bound parameter values test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +@SYMREQ REQ5792 +*/ +void BoundParameterValuesTest2() + { + (void)RSqlDatabase::Delete(KTestDbName1); + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)")); + TEST2(err, 1); + + RSqlStatement stmt; + err = stmt.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)")); + TEST2(err, KErrNone); + RSqlParamWriteStream strm; + err = strm.BindText(stmt, 0); + TEST2(err, KErrNone); + err = stmt.Exec(); + TEST2(err, 1); + stmt.Close(); + strm.Close(); + + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4077 +@SYMTestCaseDesc Bound parameter values test. + The test verifies that when a RSqlParamWriteStream object is used for binding parameter values, + it is possible to write the parameter value, then call RSqlParamWriteStream::Close() and finally - + RSqlStatement::Exec() to execute the operation (an INSERT statement). The test verifies that the record + has really been inserted and the column value is equal to the bound parameter value +@SYMTestActions Bound parameter values test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +@SYMREQ REQ5792 +*/ +void BoundParameterValuesTest3() + { + (void)RSqlDatabase::Delete(KTestDbName1); + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)")); + TEST2(err, 1); + + RSqlStatement stmt; + err = stmt.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)")); + TEST2(err, KErrNone); + RSqlParamWriteStream strm; + err = strm.BindText(stmt, 0); + TEST2(err, KErrNone); + _LIT(KText, "AAAA"); + TRAP(err, strm.WriteL(KText)); + TEST2(err, KErrNone); + TRAP(err, strm.CommitL()); + TEST2(err, KErrNone); + strm.Close(); + err = stmt.Exec(); + TEST2(err, 1); + stmt.Close(); + + TSqlScalarFullSelectQuery q(TheDb); + TRAP(err, q.SelectTextL(_L("SELECT T1 FROM A1"), TheBuf)); + TEST2(err, KErrNone); + TEST(KText() == TheBuf); + + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4083 +@SYMTestCaseDesc Bound parameter values test. + The test prepares an INSERT sql statement and inserts two records using streams to bind the parameter values. + For the second INSERT no parameter value is bound to the first parameter. The expectation is that the value + that has been bound for the first record will be used for the second record also. +@SYMTestActions Bound parameter values test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +@SYMREQ REQ5792 +*/ +void BoundParameterValuesTest4() + { + (void)RSqlDatabase::Delete(KTestDbName1); + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)")); + TEST2(err, 1); + + RSqlStatement stmt; + err = stmt.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)")); + TEST2(err, KErrNone); + + RSqlParamWriteStream strm; + err = strm.BindText(stmt, 0); + TEST2(err, KErrNone); + _LIT(KText1, "AAAA"); + TRAP(err, strm.WriteL(KText1)); + TEST2(err, KErrNone); + TRAP(err, strm.CommitL()); + TEST2(err, KErrNone); + strm.Close(); + + err = strm.BindText(stmt, 1); + TEST2(err, KErrNone); + _LIT(KText2, "BBBBBBBBBB"); + TRAP(err, strm.WriteL(KText2)); + TEST2(err, KErrNone); + TRAP(err, strm.CommitL()); + TEST2(err, KErrNone); + strm.Close(); + + err = stmt.Exec(); + TEST2(err, 1); + err = stmt.Reset(); + TEST2(err, KErrNone); + + err = strm.BindText(stmt, 1); + TEST2(err, KErrNone); + _LIT(KText3, "CCCCCCCCCCC"); + TRAP(err, strm.WriteL(KText3)); + TEST2(err, KErrNone); + TRAP(err, strm.CommitL()); + TEST2(err, KErrNone); + strm.Close(); + + err = stmt.Exec(); + TEST2(err, 1); + + stmt.Close(); + + TSqlScalarFullSelectQuery q(TheDb); + TRAP(err, q.SelectTextL(_L("SELECT T1 FROM A1 WHERE ROWID=1"), TheBuf)); + TEST2(err, KErrNone); + TEST(KText1() == TheBuf); + TRAP(err, q.SelectTextL(_L("SELECT T2 FROM A1 WHERE ROWID=1"), TheBuf)); + TEST2(err, KErrNone); + TEST(KText2() == TheBuf); + + TRAP(err, q.SelectTextL(_L("SELECT T1 FROM A1 WHERE ROWID=2"), TheBuf)); + TEST2(err, KErrNone); + TEST(KText1() == TheBuf); + TRAP(err, q.SelectTextL(_L("SELECT T2 FROM A1 WHERE ROWID=2"), TheBuf)); + TEST2(err, KErrNone); + TEST(KText3() == TheBuf); + + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4105 +@SYMTestCaseDesc Bound parameter values test. + BC test. Even though it is correct to execute only one CommitL() on a parameter stream, + it should be possible to execute more than one CommitL(). It should be possible also + the stream data to be updated after the first commit operation and the expectation is that + the updated parameter data should be used for the column value. +@SYMTestActions Bound parameter values test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +@SYMREQ REQ5792 +*/ +void BoundParameterValuesTest5() + { + (void)RSqlDatabase::Delete(KTestDbName1); + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + err = TheDb.Exec(_L("CREATE TABLE A1(T1 TEXT, T2 TEXT)")); + TEST2(err, 1); + + RSqlStatement stmt; + err = stmt.Prepare(TheDb, _L("INSERT INTO A1 VALUES(:Prm1, :Prm2)")); + TEST2(err, KErrNone); + + RSqlParamWriteStream strm; + err = strm.BindText(stmt, 0); + TEST2(err, KErrNone); + _LIT(KText1, "AAAA"); + TRAP(err, strm.WriteL(KText1)); + TEST2(err, KErrNone); + TRAP(err, strm.CommitL()); + TEST2(err, KErrNone); + TRAP(err, strm.Sink()->SeekL(MStreamBuf::EWrite, EStreamBeginning, 0)); + TEST2(err, KErrNone); + _LIT(KText2, "DTAA"); + TRAP(err, strm.WriteL(KText2)); + TEST2(err, KErrNone); + TRAP(err, strm.CommitL()); + TEST2(err, KErrNone); + strm.Close(); + + err = stmt.Exec(); + TEST2(err, 1); + + stmt.Close(); + + TSqlScalarFullSelectQuery q(TheDb); + TRAP(err, q.SelectTextL(_L("SELECT T1 FROM A1 WHERE ROWID=1"), TheBuf)); + TEST2(err, KErrNone); + TEST(KText2() == TheBuf); + + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +void PrintConfig(TSqlResourceProfiler& aProfiler) + { + TBuf8<128> config; + if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterConfig, config) == KErrNone) + { + _LIT(KCacheSize, "Cache size: %S pages\r\n"); + _LIT(KPageSize, "Page size: %S bytes\r\n"); + _LIT(KEncoding, "Encoding: %S\r\n"); + _LIT(KDefaultSoftHeapLimit, "Default soft heap limit: %S Kb\r\n"); + _LIT(KVacuumMode, "Vacuum mode: %S\r\n"); + + TPtrC KText[] = {KCacheSize(), KPageSize(), KEncoding(), KDefaultSoftHeapLimit(), KVacuumMode()}; + + for(TInt i=0;i num; + num.Copy(num8); + TheTest.Printf(KText[idx], &num); + ++idx; + } + } + } + +void PrintFileIo(TSqlResourceProfiler& aProfiler) + { + TBuf8<300> countersValues; + if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterFileIO, countersValues) == KErrNone) + { + TheTest.Printf(_L("=========================\r\n")); + _LIT(KFileCreate, "File Create"); + _LIT(KFileOpen, "File Open"); + _LIT(KFileClose, "File Close"); + _LIT(KFileDelete, "File Delete"); + _LIT(KFileRead, "File Read"); + _LIT(KFileWrite, "File Write"); + _LIT(KFileSeek, "File Seek"); + _LIT(KFileSize, "File Size"); + _LIT(KFileSetSize, "File SetSize"); + _LIT(KFileSync, "File Sync"); + _LIT(KFileDrive, "File Drive"); + _LIT(KFileAdopt, "File Adopt"); + _LIT(KFsClose, "Fs Close"); + _LIT(KFsConnect, "Fs Connect"); + _LIT(KFsGetSystemDrive, "Fs GetSystemDrive"); + _LIT(KFsCreatePrivatePath, "Fs CreatePrivatePath"); + _LIT(KFsPrivatePath, "Fs PrivatePath"); + _LIT(KFsVolumeIoParam, "Fs VolumeIoParam"); + _LIT(KFsEntry, "Fs Entry"); + _LIT(KFsAtt, "Fs Att"); + _LIT(KFileCreateTemp, "File CreateTemp"); + _LIT(KFileAttach, "File Attach"); + _LIT(KBytesWritten, "File Bytes Written"); + _LIT(KBytesRead, "File Bytes Read"); + TPtrC KText[] = + { + KFileCreate(), KFileOpen(), KFileClose(), KFileDelete(), KFileRead(), KFileWrite(), KFileSeek(), KFileSize(), + KFileSetSize(), KFileSync(), KFileDrive(), KFileAdopt(), KFsClose(), KFsConnect(), KFsGetSystemDrive(), + KFsCreatePrivatePath(), KFsPrivatePath(), KFsVolumeIoParam(), KFsEntry(), KFsAtt(), KFileCreateTemp(), + KFileAttach(), KBytesWritten(), KBytesRead() + }; + + for(TInt i=0;i num; + num.Copy(num8); + TheTest.Printf(_L("==Operation %S, count %S\r\n"), &KText[idx], &num); + ++idx; + } + } + } + +void PrintOsCall(TSqlResourceProfiler& aProfiler) + { + TBuf8<300> countersValues; + if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterOsCall, countersValues) == KErrNone) + { + TheTest.Printf(_L("=========================\r\n")); + _LIT(KEOsFileClose, "FileClose"); + _LIT(KEOsFileRead, "FileRead"); + _LIT(KEOsFileWrite, "FileWrite"); + _LIT(KEOsFileTruncate, "FileTruncate"); + _LIT(KEOsFileSync, "FileSync"); + _LIT(KEOsFileFileSize, "FileSize"); + _LIT(KEOsFileLock, "FileLock"); + _LIT(KEOsFileUnlock, "FileUnlock"); + _LIT(KEOsFileCheckReservedLock, "FileCheckReservedLock"); + _LIT(KEOsFileFileControl, "FileIoControl"); + _LIT(KEOsFileSectorSize, "FileSectorSize"); + _LIT(KEOsFileDeviceCharacteristics, "FileDeviceCharacteristics"); + _LIT(KEOsVfsOpen, "VfsOpen"); + _LIT(KEOsVfsDelete, "VfsDelete"); + _LIT(KEOsVfsAccess, "VfsAccess"); + _LIT(KEOsVfsFullPathName, "VfsFullPathName"); + _LIT(KEOsVfsRandomness, "VfsRandomnes"); + _LIT(KEOsVfsSleep, "VfsSleep"); + _LIT(KEOsVfsCurrentTime, "VfsCurrentTime"); + _LIT(KEOsVfsGetLastError, "VfsGetLastError"); + TPtrC KText[] = + { + KEOsFileClose(), KEOsFileRead(), KEOsFileWrite(), KEOsFileTruncate(), KEOsFileSync(), + KEOsFileFileSize(), KEOsFileLock(), KEOsFileUnlock(), KEOsFileCheckReservedLock(), KEOsFileFileControl(), + KEOsFileSectorSize(), KEOsFileDeviceCharacteristics(), + KEOsVfsOpen(), KEOsVfsDelete(), KEOsVfsAccess(), KEOsVfsFullPathName(), KEOsVfsRandomness(), KEOsVfsSleep(), + KEOsVfsCurrentTime(), KEOsVfsGetLastError()}; + + for(TInt i=0;i num; + num.Copy(num8); + TheTest.Printf(_L("==Operation %S, count %S\r\n"), &KText[idx], &num); + ++idx; + } + } + } + +void PrintOsCallTime(TSqlResourceProfiler& aProfiler) + { + TBuf8<300> callTimes; + if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterOsCallTime, callTimes) == KErrNone) + { + TheTest.Printf(_L("=========================\r\n")); + _LIT(KEOsFileClose, "FileClose"); + _LIT(KEOsFileRead, "FileRead"); + _LIT(KEOsFileWrite, "FileWrite"); + _LIT(KEOsFileTruncate, "FileTruncate"); + _LIT(KEOsFileSync, "FileSync"); + _LIT(KEOsFileFileSize, "FileSize"); + _LIT(KEOsFileLock, "FileLock"); + _LIT(KEOsFileUnlock, "FileUnlock"); + _LIT(KEOsFileCheckReservedLock, "FileCheckReservedLock"); + _LIT(KEOsFileFileControl, "FileIoControl"); + _LIT(KEOsFileSectorSize, "FileSectorSize"); + _LIT(KEOsFileDeviceCharacteristics, "FileDeviceCharacteristics"); + _LIT(KEOsVfsOpen, "VfsOpen"); + _LIT(KEOsVfsDelete, "VfsDelete"); + _LIT(KEOsVfsAccess, "VfsAccess"); + _LIT(KEOsVfsFullPathName, "VfsFullPathName"); + _LIT(KEOsVfsRandomness, "VfsRandomnes"); + _LIT(KEOsVfsSleep, "VfsSleep"); + _LIT(KEOsVfsCurrentTime, "VfsCurrentTime"); + _LIT(KEOsVfsGetLastError, "VfsGetLastError"); + TPtrC KText[] = + { + KEOsFileClose(), KEOsFileRead(), KEOsFileWrite(), KEOsFileTruncate(), KEOsFileSync(), + KEOsFileFileSize(), KEOsFileLock(), KEOsFileUnlock(), KEOsFileCheckReservedLock(), KEOsFileFileControl(), + KEOsFileSectorSize(), KEOsFileDeviceCharacteristics(), + KEOsVfsOpen(), KEOsVfsDelete(), KEOsVfsAccess(), KEOsVfsFullPathName(), KEOsVfsRandomness(), KEOsVfsSleep(), + KEOsVfsCurrentTime(), KEOsVfsGetLastError()}; + + for(TInt i=0;i num; + num.Copy(num8); + TheTest.Printf(_L("==Operation %S, time %S us\r\n"), &KText[idx], &num); + ++idx; + } + } + } + +void PrintIpc(TSqlResourceProfiler& aProfiler) + { + TBuf8<300> countersValues; + if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterIpc, countersValues) == KErrNone) + { + TheTest.Printf(_L("=========================\r\n")); + _LIT(KIpcRq, "IPC requests"); + _LIT(KIpcRead, "IPC read"); + _LIT(KIpcWrite, "IPC write"); + _LIT(KIpcReadBytes, "IPC read bytes"); + _LIT(KIpcWriteBytes, "IPC write bytes"); + TPtrC KText[] = + { + KIpcRq(), KIpcRead(), KIpcWrite(), KIpcReadBytes(), KIpcWriteBytes() + }; + + for(TInt i=0;i num; + num.Copy(num8); + TheTest.Printf(_L("==Operation %S, count %S\r\n"), &KText[idx], &num); + ++idx; + } + } + } + +void PrintMemory(TSqlResourceProfiler& aProfiler) + { + TBuf8<300> countersValues; + if(aProfiler.Query(TSqlResourceProfiler::ESqlCounterMemory, countersValues) == KErrNone) + { + TheTest.Printf(_L("=========================\r\n")); + _LIT(KMemorySrvAllocatedCnt, "Server allocated cnt"); + _LIT(KMemorySrvAllocatedSize, "Server allocated size"); + _LIT(KMemorySrvFreeSpace, "Server free space"); + _LIT(KMemorySrvLargestBlockSize, "Server larges block size"); + _LIT(KMemorySQLiteAllocatedCnt, "SQLite allocated cnt"); + _LIT(KMemorySQLiteReallocatedCnt, "SQLite reallocated cnt"); + _LIT(KMemorySQLiteFreedCnt, "SQLite freed cnt"); + _LIT(KMemorySQLiteAllocatedBytes, "SQLite allocated bytes"); + _LIT(KMemorySQLiteFreedBytes, "SQLite freed bytes"); + _LIT(KMemorySQLiteAllocTime, "SQLite alloc, us"); + _LIT(KMemorySQLiteReallocTime, "SQLite realloc, us"); + _LIT(KMemorySQLiteFreeTime, "SQLite free, us"); + TPtrC KText[] = + { + KMemorySrvAllocatedCnt(), KMemorySrvAllocatedSize(), KMemorySrvFreeSpace(), KMemorySrvLargestBlockSize(), + KMemorySQLiteAllocatedCnt(), KMemorySQLiteReallocatedCnt(), KMemorySQLiteFreedCnt(), + KMemorySQLiteAllocatedBytes(), KMemorySQLiteFreedBytes(), + KMemorySQLiteAllocTime(), KMemorySQLiteReallocTime(), KMemorySQLiteFreeTime() + }; + + for(TInt i=0;i num; + num.Copy(num8); + TheTest.Printf(_L("==%S=%S\r\n"), &KText[idx], &num); + ++idx; + } + } + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4088 +@SYMTestCaseDesc TSqlResouceProfiler - file I/O and configuration test. + The test enables the file I/O profiling and then executes a simple INSERT statement + and prints out the profiling results. The test also prints the current database configuration. +@SYMTestActions TSqlResouceProfiler - file I/O and configuration test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority Medium +@SYMREQ REQ5792 +*/ +void ProfilerTest() + { + (void)RSqlDatabase::Delete(KTestDbName1); + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER, T TEXT)")); + TEST2(err, 1); + + TSqlResourceProfiler profiler(TheDb); + + PrintConfig(profiler); + + (void)profiler.Start(TSqlResourceProfiler::ESqlCounterFileIO); + (void)profiler.Start(TSqlResourceProfiler::ESqlCounterOsCall); + (void)profiler.Start(TSqlResourceProfiler::ESqlCounterOsCallTime); + (void)profiler.Start(TSqlResourceProfiler::ESqlCounterIpc); + (void)profiler.Start(TSqlResourceProfiler::ESqlCounterMemory); + + (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterFileIO); + (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterOsCall); + (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterOsCallTime); + (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterIpc); + (void)profiler.Reset(TSqlResourceProfiler::ESqlCounterMemory); + + err = TheDb.Exec(_L("INSERT INTO A VALUES(1, 'ABCDEEFGH')")); + TEST2(err, 1); + + PrintFileIo(profiler); + PrintOsCall(profiler); + PrintOsCallTime(profiler); + PrintIpc(profiler); + PrintMemory(profiler); + + (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterIpc); + (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterOsCallTime); + (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterOsCall); + (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterFileIO); + (void)profiler.Stop(TSqlResourceProfiler::ESqlCounterMemory); + + TheDb.Close(); + (void)RSqlDatabase::Delete(KTestDbName1); + } + +TInt CompoundSelectStackOverflowThreadFunc(void* aData) + { + CTrapCleanup* tc = CTrapCleanup::New(); + TEST(tc != NULL); + + User::SetJustInTime(EFalse); // disable debugger panic handling + + TInt* cntptr = reinterpret_cast (aData); + TEST(cntptr != NULL); + const TInt KSelectStmtCnt = *cntptr; + + HBufC* buf = HBufC::New(KSelectStmtCnt * 25 + 32);//enough for the "SELECT I FROM A UNION SELECT I FROM A..." string + if(!buf) + { + delete tc; + return KErrNoMemory; + } + TPtr sql = buf->Des(); + + (void)RSqlDatabase::Delete(KTestDbName1); + RSqlDatabase db; + TInt err = db.Create(KTestDbName1); + if(err != KErrNone) + { + delete buf; + return err; + } + err = db.Exec(_L("CREATE TABLE A(I INTEGER);INSERT INTO A VALUES(1);")); + if(err < 1) + { + delete buf; + return err; + } + + for(TInt i=0;i0;--cnt) + { + TheTest.Printf(_L("SELECT statement count: %d\r\n"), cnt); + RThread thread; + _LIT(KThreadName,"S2Thread"); //stack minheap maxheap + TInt err = thread.Create(KThreadName, &CompoundSelectStackOverflowThreadFunc, 0x2000, 0x00100000, 0x02000000, &cnt); + TEST2(err, KErrNone); + + TRequestStatus status; + thread.Logon(status); + TEST2(status.Int(), KRequestPending); + thread.Resume(); + User::WaitForRequest(status); + User::SetJustInTime(ETrue); // enable debugger panic handling + + TInt exitType = thread.ExitType(); + const TDesC& exitCategory = thread.ExitCategory(); + TInt exitReason = thread.ExitReason(); + TheTest.Printf(_L("Exit type: %d, exit reason: %d, exit category: %S\r\n"), exitType, exitReason, &exitCategory); + thread.Close(); + if(exitReason == KErrServerTerminated) //SQL server --> stack overflow + { + continue; + } + TEST2(exitReason, KErrNone); + TheTest.Printf(_L(" The test has succeeded with SELECT statement count=%d\r\n"), cnt); + break; + } + } + +/** +@SYMTestCaseID PDS-SQL-CT-4198 +@SYMTestCaseDesc Expired SQL statements test. + The test creates a database and opens 2 connections to that database. + Connection 2 prepares couple of SELECT and INSERT statements (8-bit and 16-bit). + Then connection 1 renames the table used in the already prepared statements. + Connection 2 attempts to execute the prepared statements. The execution should fail + because the database schema has changed after they were prepared. +@SYMTestActions Expired SQL statements test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +@SYMDEF DEF145236 +*/ +void ExpiredStmtTest() + { + (void)RSqlDatabase::Delete(KTestDbName1); + //Create a database and create db connection 1. + TInt err = TheDb.Create(KTestDbName1); + TEST2(err, KErrNone); + err = TheDb.Exec(_L("CREATE TABLE A(C1 INTEGER)")); + TEST(err >= 0); + err = TheDb.Exec(_L("INSERT INTO A(C1) VALUES(1)")); + TEST2(err, 1); + + //Create db connection 2 to the same database, as db connection 1. + RSqlDatabase db2; + err = db2.Open(KTestDbName1); + TEST2(err, KErrNone); + + //Db connection 2. Prepare SELECT and INSERT, 8-bit and 16-bit statements. + RSqlStatement stmt1, stmt2, stmt3, stmt4; + err = stmt1.Prepare(db2, _L("SELECT * FROM A")); + TEST2(err, KErrNone); + err = stmt2.Prepare(db2, _L8("SELECT * FROM A")); + TEST2(err, KErrNone); + err = stmt3.Prepare(db2, _L("INSERT INTO A(C1) VALUES(2)")); + TEST2(err, KErrNone); + err = stmt4.Prepare(db2, _L8("INSERT INTO A(C1) VALUES(3)")); + TEST2(err, KErrNone); + + //Modify the A table structure from the other connection + //err = TheDb.Exec(_L("ALTER TABLE A ADD C2 INTEGER")); + err = TheDb.Exec(_L("ALTER TABLE A RENAME TO B")); + TEST(err >= 0); + + //Try to execute the already prepared statements. + err = stmt1.Next(); + TEST2(err, KSqlErrSchema); + err = stmt1.Next(); + TEST(err != KSqlAtRow); + err = stmt2.Next(); + TEST(err != KSqlAtRow); + err = stmt3.Exec(); + TEST(err < 0); + err = stmt4.Exec(); + TEST(err < 0); + // + stmt4.Close(); + stmt3.Close(); + stmt2.Close(); + stmt1.Close(); + db2.Close(); + TheDb.Close(); + err = RSqlDatabase::Delete(KTestDbName1); + TEST2(err, KErrNone); + } + +void DoTestsL() + { + TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3512 RSqlStatement::ColumnCount() tests ")); + ColumnCountTest(); + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3513 RSqlStatement::ColumnCount(), non-SELECT tests ")); + ColumnCountTest2(); + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3514 RSqlStatement::DeclaredColumnType() tests ")); + DeclaredColumnTypeTest(); + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4017 RSqlStatement::ColumnName() tests")); + ColumnNameTest(); + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4018 RSqlStatement::ParameterName() and RSqlStatement::ParamName() tests")); + ParamNameTest(); + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4006 DEF115300 - SqlSrv.EXE::!SQL Server when preparing invalid LEFT JOIN sql query ")); + DEF115300(); + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4007 DEF115331 - SQL, bad code coverage for db reindexing if default collation has changed ")); + DEF115331L(); + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4079 RSqlDatabase::Create() and RSqlDatabase::Open() - injection tests")); + InjectionTest(); + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4038 Two connections test")); + TwoConnectionsTest(); + TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4080 SQL server stack overflow test")); + SqlServerStackOverflowTest(); + TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4086 RSqlBlobWriteStream/RSqlBlobReadStream injection test")); + BlobStreamInjectionTest(); + TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4087 Bound parameter values test 1")); + BoundParameterValuesTest(); + TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4076 Bound parameter values test 2")); + BoundParameterValuesTest2(); + TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4077 Bound parameter values test 3")); + BoundParameterValuesTest3(); + TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4083 Bound parameter values test 4")); + BoundParameterValuesTest4(); + TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4105 Bound parameter values test 5")); + BoundParameterValuesTest5(); + TheTest.Next( _L(" @SYMTestCaseID:SYSLIB-SQL-UT-4088 TSqlResourceProfiler - file I/O and configuration test")); + ProfilerTest(); + TheTest.Next( _L(" Compound SELECT, stack overflow test")); + CompoundSelectStackOverflowTest(); + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4198 Expired statements test")); + ExpiredStmtTest(); + } + +TInt E32Main() + { + TheTest.Title(); + + CTrapCleanup* tc = CTrapCleanup::New(); + + __UHEAP_MARK; + + CreateTestEnv(); + DeleteTestFiles(); + TRAPD(err, DoTestsL()); + DeleteTestFiles(); + TEST2(err, KErrNone); + + __UHEAP_MARKEND; + + TheTest.End(); + TheTest.Close(); + + delete tc; + + User::Heap().Check(); + return KErrNone; + }