diff -r 000000000000 -r 08ec8eefde2f persistentstorage/sqlite3api/TEST/t_sqlitedef.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/sqlite3api/TEST/t_sqlitedef.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,504 @@ +// Copyright (c) 2008-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 +#include +#include +#include +#include + +#include "e32des16.h" + + +static RTest TheTest(_L("t_sqlitedef")); +static RFs TheFs; + +static sqlite3* TheDb = NULL; +static sqlite3* TheDb2 = NULL; + +const char* KTestDir = "c:\\test\\"; +const char* KTestDb = "c:\\test\\t_sqlitedef.db"; +const char* KTestDb2 = "c:\\t_sqlitedef.db"; + +static void DeleteFile(const char* aFileName) + { + TFileName fname; + fname.Copy(TPtrC8((const TUint8*)aFileName)); + (void)TheFs.Delete(fname); + } + +/** + * Creates the database file and the directory that the test file will be stored. + */ +static void CreateTestEnv() + { + TInt err = TheFs.Connect(); + TheTest(err == KErrNone); + + err = TheFs.ShareAuto(); + TheTest(err == KErrNone); + + TFileName testDir; + testDir.Copy(TPtrC8((const TUint8*)KTestDir)); + err = TheFs.MkDir(testDir); + TheTest(err == KErrNone || err == KErrAlreadyExists); + + TFileName fname; + fname.Copy(TPtrC8((const TUint8*)KTestDb)); + (void)TheFs.Delete(fname); + } +/** + * Closes the database and erases the database file, but not the directory. + */ +static void DestroyTestEnv() + { + if(TheDb2) + { + (void)sqlite3_close(TheDb2); + TheDb2 = 0; + } + if(TheDb) + { + (void)sqlite3_close(TheDb); + TheDb = 0; + } + if(TheFs.Handle() != KNullHandle) + { + DeleteFile(KTestDb2); + DeleteFile(KTestDb); + } + TheFs.Close(); + } + + +/////////////////////////////////////////////////////////////////////////////////////// +//Test macros and functions + +static void PrintErrMsg() + { + TBuf<256> buf; + if(TheDb) + { + const char* msg = sqlite3_errmsg(TheDb); + buf.Copy(TPtrC8((const TUint8*)msg)); + RDebug::Print(_L("*** Db1 err msg: \"%S\"\r\n"), &buf); + } + if(TheDb2) + { + const char* msg = sqlite3_errmsg(TheDb2); + buf.Copy(TPtrC8((const TUint8*)msg)); + RDebug::Print(_L("*** Db2 err msg: \"%S\"\r\n"), &buf); + } + } + +static void Check(TInt aValue, TInt aLine) + { + if(!aValue) + { + PrintErrMsg(); + DestroyTestEnv(); + TheTest(EFalse, aLine); + } + } +static void Check(TInt aValue, TInt aExpected, TInt aLine) + { + if(aValue != aExpected) + { + PrintErrMsg(); + 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__) + +/////////////////////////////////////////////////////////////////////////////////////// +// + +TInt ThreadFunc(void*) + { + User::SetJustInTime(EFalse); // disable debugger panic handling + + CTrapCleanup* tc = CTrapCleanup::New(); + TEST(tc != NULL); + + TInt err = sqlite3_open(KTestDb, &TheDb2); + TEST2(err, SQLITE_OK); + + err = sqlite3_exec(TheDb2, "CREATE TABLE A(Id INTEGER,Name TEXT)", 0, 0, 0); + TEST2(err, SQLITE_OK); + err = sqlite3_exec(TheDb2, "INSERT INTO A VALUES(1, 'AAA')", 0, 0, 0); + TEST2(err, SQLITE_OK); + + sqlite3_close(TheDb2); + TheDb2 = NULL; + + delete tc; + + return 0; + } + +/** +@SYMTestCaseID PDS-SQLITE3-UT-4029 +@SYMTestCaseDesc Sqlite file handle test + The test verifies that a database can be opened from different threads in the same process, + when the shared page cache is enabled. In this case the database file handle is shared between the + threads that open the database. +@SYMTestPriority High +@SYMTestActions Sqlite file handle test +@SYMTestExpectedResults Test must not fail +@SYMREQ REQ10424 +*/ +void FileHandleTest() + { + DeleteFile(KTestDb); + sqlite3_enable_shared_cache(1);//this is a per-process setting (was per-thread in SQLite 3.3.17) + TInt err = sqlite3_open(KTestDb, &TheDb); + TEST2(err, SQLITE_OK); + + err = sqlite3_exec(TheDb, "CREATE TABLE B(Id INTEGER,Name TEXT)", 0, 0, 0); + TEST2(err, SQLITE_OK); + err = sqlite3_exec(TheDb, "INSERT INTO B VALUES(1, 'BBB')", 0, 0, 0); + TEST2(err, SQLITE_OK); + + //////////////////////////////////////////////////////////// + // The created thread uses the heap of the creating thread + // The same SQLite database can be accessed from different threads in + // shared page cache mode only if the threads share the same heap. + // The database file handle will be shared between threads. + //////////////////////////////////////////////////////////// + RDebug::Print(_L("*** Shared heap\r\n")); + RThread thr; + err = thr.Create(_L("TestThr"), &ThreadFunc, KDefaultStackSize, NULL, NULL); + TEST2(err, KErrNone); + thr.Resume(); + TRequestStatus stat; + thr.Logon(stat); + User::WaitForRequest(stat); + User::SetJustInTime(ETrue); // enable debugger panic handling + + TInt exitType = thr.ExitType(); + TInt exitReason = thr.ExitReason(); + thr.Close(); + TEST2(exitReason, 0); + TEST2(exitType, EExitKill); + //////////////////////////////////////////////////////////// + + sqlite3_close(TheDb); + TheDb = NULL; + } + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////// Sqlite3 DLL OOM test //////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +/** +@SYMTestCaseID PDS-SQLITE3-CT-4028 +@SYMTestCaseDesc Sqlite OOM test + Precondition: none + A standard OOM test checks the sqlite3 DLL for memory leaks documented + on the raised defect, to check if the applied fix is working. Before + the fix the test was failing with PANIC USER:84 on the second iteration + loop on DoTest() +@SYMTestPriority Medium +@SYMTestActions Sqlite OOM test - + Opens the database file. + Calls sqlite3_prepare16_v2() + Closes database + Checks memory leaks + Repeats the above indefinitely until SQLITE_OK +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF121506 +*/ +void DEF121506() + { + RDebug::Print(_L("Iteration: \r\n")); + for (TInt it = 1; ; ++it) + { + RDebug::Print(_L("%d "), it); + TInt c1 = User::CountAllocCells(); + __UHEAP_SETFAIL(RHeap::EDeterministic, it); + + TInt err = sqlite3_open(KTestDb,&TheDb); + + if(err == SQLITE_OK) + { + sqlite3_stmt* stmt = 0; + const void* tail = 0; + err = sqlite3_prepare16_v2(TheDb, + L"CREATE TABLE Sample(Id INTEGER PRIMARY KEY NOT NULL, Name TEXT NOT NULL UNIQUE COLLATE NOCASE);", + -1, &stmt, &tail); + (void)sqlite3_finalize(stmt); + } + + (void)sqlite3_close(TheDb); + TheDb = NULL; + __UHEAP_RESET; + + TInt c2 = User::CountAllocCells(); + if (c1 != c2) + { + RDebug::Print(_L("\r\n*** OOM Test failed\r\n")); + TEST(EFalse); + } + else if (err == SQLITE_OK) + { + RDebug::Print(_L("\r\n*** OOM Test passed\r\n")); + break; + } + TEST2(err, SQLITE_NOMEM); + } + } + +/** +@SYMTestCaseID PDS-SQLITE3-CT-4046 +@SYMTestCaseDesc [sqlite3] can't execute sql sequence in transcation. +@SYMTestPriority High +@SYMTestActions The test deletes the test application private data cage. + Then the test creates a database and attempts to execute a set + of SQL statements, some of them will need a temporary file to be created. + Since the test application private data cage (so the session path) does not exist, + the SQLite OS porting layer will fail to create the requested temporary file and + will fail with KErrPathNotFound error. + The OS porting layer was fixed to create the session path if the temporary file creation error + is KErrPathNotFound. +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF140020 +*/ +void DEF140020() + { + //Remove the private data cage + CFileMan* fm = 0; + TRAPD(err, fm = CFileMan::NewL(TheFs)); + TEST(fm != 0); + + TFileName privatePath; + err = TheFs.SessionPath(privatePath); + TEST2(err, KErrNone); + err = fm->RmDir(privatePath); + TEST(err == KErrNone || err == KErrPathNotFound); + + delete fm; + fm = 0; + + TEST2((TUint)TheDb, 0); + err = sqlite3_open(KTestDb2, &TheDb); + TEST2(err, SQLITE_OK); + + const char * stmt[] ={ + "CREATE TABLE fortest (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, intcol INTEGER NOT NULL, charcol CHAR(255) ) ", + "INSERT INTO fortest(intcol, charcol) VALUES(1,'111');", + "BEGIN TRANSACTION;", + "CREATE TABLE t1_backup(id INTEGER, intcol INTEGER NOT NULL);", + "INSERT INTO t1_backup SELECT id, intcol FROM fortest;", + "DROP TABLE fortest;", + "CREATE TABLE fortest (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, intcol INTEGER NOT NULL);", + "INSERT INTO fortest(id, intcol) SELECT id,intcol FROM t1_backup;", + "DROP TABLE t1_backup;", + "select count(*) from fortest;", + "COMMIT;", + "select count(*) from fortest;", + "CREATE TABLE t1_backup(id INTEGER, intcol INTEGER NOT NULL);", + "INSERT INTO t1_backup SELECT id, intcol FROM fortest;", + "DROP TABLE fortest;", + "CREATE TABLE fortest (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, intcol INTEGER NOT NULL);", + "INSERT INTO fortest(id, intcol) SELECT id,intcol FROM t1_backup;", + "DROP TABLE t1_backup;", + }; + + char* msg = NULL; + int i = 0; + for (i = 0; i < sizeof(stmt) / sizeof(*stmt); i++) + { + err = sqlite3_exec(TheDb, stmt[i], NULL, NULL, &msg); + TEST2(err, SQLITE_OK); + } + + sqlite3_close(TheDb); + TheDb = 0; + DeleteFile(KTestDb2); + } + +/** +@SYMTestCaseID PDS-SQLITE3-CT-4047 +@SYMTestCaseDesc Test for DEF143066: SQLITE, "CREATE INDEX" sql crashes the SQLite library. + The test creates a database with one empty table and establishes two connections + to that database. Then, while the first connection is at the middle of a read + transaction, the second connection attempts to create an index. + If the defect is not fixed, the SQLite library will crash. +@SYMTestPriority High +@SYMTestActions DEF143066: SQLITE, "CREATE INDEX" sql crashes the SQLite library. +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF143066 +*/ +void DEF143066() + { + DeleteFile(KTestDb); + sqlite3_enable_shared_cache(1); + int err = sqlite3_open(KTestDb, &TheDb); + TEST2(err, SQLITE_OK); + + err = sqlite3_exec(TheDb, "CREATE TABLE T0(Thread INTEGER, LocalIndex INTEGER, Inserts INTEGER, Updates INTEGER, IndexMod8 INTEGER)", 0, 0, 0); + TEST2(err, SQLITE_OK); + + err = sqlite3_open(KTestDb, &TheDb2); + TEST2(err, SQLITE_OK); + + sqlite3_stmt* stmt = 0; + const char* tail = 0; + err = sqlite3_prepare_v2(TheDb, "SELECT COUNT(Thread) FROM T0 WHERE Thread = 0", -1, &stmt, &tail); + TEST2(err, SQLITE_OK); + + err = sqlite3_step(stmt); + TEST2(err, SQLITE_ROW); + + err = sqlite3_exec(TheDb2, "CREATE INDEX T0INDEX ON T0(Thread,IndexMod8)", 0, 0, 0); + TEST2(err, SQLITE_LOCKED); + + (void)sqlite3_finalize(stmt); + sqlite3_close(TheDb2); + TheDb2 = NULL; + sqlite3_close(TheDb); + TheDb = NULL; + DeleteFile(KTestDb); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4048 +@SYMTestCaseDesc Test for DEF143151: SQLite, strftime() returns incorrect result. + The test takes the current universal time (using TTime) + and the current time retrieved from the SQLite library. + The test compares the times and expects the difference to be no more than + 1 second. +@SYMTestPriority High +@SYMTestActions DEF143151: SQLite, strftime() returns incorrect result +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF143151 +*/ +void DEF143151() + { + DeleteFile(KTestDb); + int err = sqlite3_open(KTestDb, &TheDb); + TEST2(err, SQLITE_OK); + + //Home date & time + TBuf<50> dtstr1; + TTime time; + time.UniversalTime(); + TDateTime dt = time.DateTime(); + + sqlite3_stmt* stmt = 0; + const char* tail = 0; + err = sqlite3_prepare_v2(TheDb, "SELECT strftime('%Y-%m-%d,%H:%M:%S','now')", -1, &stmt, &tail); + TEST2(err, SQLITE_OK); + err = sqlite3_step(stmt); + TEST2(err, SQLITE_ROW); + + //SQLite date & time + const unsigned char* s = sqlite3_column_text(stmt, 0); + TEST(s != NULL); + TBuf<50> dtstr2; + dtstr2.Copy(TPtrC8(s)); + sqlite3_finalize(stmt); + + sqlite3_close(TheDb); + TheDb = NULL; + DeleteFile(KTestDb); + + dtstr1.Format(_L("%04d-%02d-%02d,%02d:%02d:%02d"), dt.Year(), dt.Month() + 1, dt.Day() + 1, dt.Hour(), dt.Minute(), dt.Second()); + TheTest.Printf(_L("Universal date&time=\"%S\"\n"), &dtstr1); + TheTest.Printf(_L("SQLite date&time=\"%S\"\n"), &dtstr2); + + //Comapare and fail if dates are not equal (+- 1 second) + TLex lex; + lex = dtstr2.Mid(0, 4); + TInt sqlyear; + err = lex.Val(sqlyear); + TEST2(err, KErrNone); + + lex = dtstr2.Mid(5, 2); + TInt sqlmonth; + err = lex.Val(sqlmonth); + TEST2(err, KErrNone); + + lex = dtstr2.Mid(8, 2); + TInt sqlday; + err = lex.Val(sqlday); + TEST2(err, KErrNone); + + lex = dtstr2.Mid(11, 2); + TInt sqlhour; + err = lex.Val(sqlhour); + TEST2(err, KErrNone); + + lex = dtstr2.Mid(14, 2); + TInt sqlminute; + err = lex.Val(sqlminute); + TEST2(err, KErrNone); + + lex = dtstr2.Mid(17, 2); + TInt sqlsecond; + err = lex.Val(sqlsecond); + TEST2(err, KErrNone); + + TDateTime sqldt(sqlyear, (TMonth)(sqlmonth - 1), sqlday - 1, sqlhour, sqlminute, sqlsecond, 0); + TTime sqltime(sqldt); + TTimeIntervalSeconds diff; + err = sqltime.SecondsFrom(time, diff); + TEST2(err, KErrNone); + TEST(diff.Int() <= 1); + } + +void DoTest() + { + TheTest.Start(_L("@SYMTestCaseID:PDS-SQLITE3-UT-4029: SQLite file handle test")); + FileHandleTest(); + + TheTest.Next(_L("@SYMTestCaseID:PDS-SQLITE3-CT-4028: DEF121506 test")); + DEF121506(); + + TheTest.Next(_L("@SYMTestCaseID:PDS-SQLITE3-CT-4046: DEF140020 test")); + DEF140020(); + + TheTest.Next(_L("@SYMTestCaseID:PDS-SQLITE3-CT-4047: SQLITE, \"CREATE INDEX\" sql crashes the SQLite library")); + DEF143066(); + + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-4048 DEF143151: SQLite, strftime() returns incorrect result")); + DEF143151(); + } + +/////////////////////////////////////////////////////////////////////////////////////// + +TInt E32Main() + { + TheTest.Title(); + CTrapCleanup* tc = CTrapCleanup::New(); + + __UHEAP_MARK; + + CreateTestEnv(); + DoTest(); + DestroyTestEnv(); + + __UHEAP_MARKEND; + + TheTest.End(); + TheTest.Close(); + delete tc; + User::Heap().Check(); + return KErrNone; + }