persistentstorage/sqlite3api/TEST/t_sqlitedef.cpp
changeset 0 08ec8eefde2f
child 23 26645d81f48d
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #include <e32test.h>
       
    18 #include <e32uid.h>
       
    19 #include <f32file.h>
       
    20 #include <e32math.h>
       
    21 #include <sqlite3.h>
       
    22 
       
    23 #include "e32des16.h"
       
    24 
       
    25 
       
    26 static RTest TheTest(_L("t_sqlitedef"));
       
    27 static RFs	TheFs;
       
    28 
       
    29 static sqlite3* TheDb = NULL;
       
    30 static sqlite3* TheDb2 = NULL;
       
    31 
       
    32 const char* KTestDir = "c:\\test\\";
       
    33 const char* KTestDb  = "c:\\test\\t_sqlitedef.db";
       
    34 const char* KTestDb2  = "c:\\t_sqlitedef.db";
       
    35 
       
    36 static void DeleteFile(const char* aFileName)
       
    37 	{
       
    38 	TFileName fname;
       
    39 	fname.Copy(TPtrC8((const TUint8*)aFileName));
       
    40 	(void)TheFs.Delete(fname);
       
    41 	}
       
    42 
       
    43 /**
       
    44  * Creates the database file and the directory that the test file will be stored.
       
    45  */
       
    46 static void CreateTestEnv()
       
    47     {
       
    48 	TInt err = TheFs.Connect();
       
    49 	TheTest(err == KErrNone);
       
    50 	
       
    51 	err = TheFs.ShareAuto();
       
    52 	TheTest(err == KErrNone);
       
    53 
       
    54     TFileName testDir;
       
    55     testDir.Copy(TPtrC8((const TUint8*)KTestDir));
       
    56 	err = TheFs.MkDir(testDir);
       
    57 	TheTest(err == KErrNone || err == KErrAlreadyExists);
       
    58 	
       
    59 	TFileName fname;
       
    60 	fname.Copy(TPtrC8((const TUint8*)KTestDb));
       
    61 	(void)TheFs.Delete(fname);
       
    62 	}
       
    63 /**
       
    64  * Closes the database and erases the database file, but not the directory.
       
    65  */
       
    66 static void DestroyTestEnv()
       
    67 	{
       
    68 	if(TheDb2)
       
    69 		{
       
    70 		(void)sqlite3_close(TheDb2);
       
    71 		TheDb2 = 0;
       
    72 		}
       
    73 	if(TheDb)
       
    74 		{
       
    75 		(void)sqlite3_close(TheDb);
       
    76 		TheDb = 0;
       
    77 		}
       
    78 	if(TheFs.Handle() != KNullHandle)
       
    79 		{
       
    80 		DeleteFile(KTestDb2);
       
    81 		DeleteFile(KTestDb);
       
    82 		}
       
    83 	TheFs.Close();
       
    84 	}
       
    85 
       
    86 
       
    87 ///////////////////////////////////////////////////////////////////////////////////////
       
    88 //Test macros and functions
       
    89 
       
    90 static void PrintErrMsg()
       
    91 	{
       
    92 	TBuf<256> buf;
       
    93 	if(TheDb)
       
    94 		{
       
    95 		const char* msg = sqlite3_errmsg(TheDb);	
       
    96 		buf.Copy(TPtrC8((const TUint8*)msg));
       
    97 		RDebug::Print(_L("*** Db1 err msg: \"%S\"\r\n"), &buf);
       
    98 		}
       
    99 	if(TheDb2)
       
   100 		{
       
   101 		const char* msg = sqlite3_errmsg(TheDb2);	
       
   102 		buf.Copy(TPtrC8((const TUint8*)msg));
       
   103 		RDebug::Print(_L("*** Db2 err msg: \"%S\"\r\n"), &buf);
       
   104 		}
       
   105 	}
       
   106 
       
   107 static void Check(TInt aValue, TInt aLine)
       
   108 	{
       
   109 	if(!aValue)
       
   110 		{
       
   111 		PrintErrMsg();
       
   112 		DestroyTestEnv();
       
   113 		TheTest(EFalse, aLine);
       
   114 		}
       
   115 	}
       
   116 static void Check(TInt aValue, TInt aExpected, TInt aLine)
       
   117 	{
       
   118 	if(aValue != aExpected)
       
   119 		{
       
   120 		PrintErrMsg();
       
   121 		DestroyTestEnv();
       
   122 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
       
   123 		TheTest(EFalse, aLine);
       
   124 		}
       
   125 	}
       
   126 #define TEST(arg) ::Check((arg), __LINE__)
       
   127 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
       
   128 
       
   129 ///////////////////////////////////////////////////////////////////////////////////////
       
   130 //
       
   131 
       
   132 TInt ThreadFunc(void*)
       
   133 	{
       
   134 	User::SetJustInTime(EFalse);	// disable debugger panic handling
       
   135 	
       
   136 	CTrapCleanup* tc = CTrapCleanup::New();
       
   137 	TEST(tc != NULL);
       
   138 
       
   139     TInt err = sqlite3_open(KTestDb, &TheDb2); 
       
   140 	TEST2(err, SQLITE_OK);
       
   141 
       
   142     err = sqlite3_exec(TheDb2, "CREATE TABLE A(Id INTEGER,Name TEXT)", 0, 0, 0);
       
   143 	TEST2(err, SQLITE_OK);
       
   144     err = sqlite3_exec(TheDb2, "INSERT INTO A VALUES(1, 'AAA')", 0, 0, 0);
       
   145 	TEST2(err, SQLITE_OK);
       
   146 
       
   147     sqlite3_close(TheDb2);
       
   148     TheDb2 = NULL;
       
   149 
       
   150 	delete tc;	
       
   151 
       
   152 	return 0;
       
   153 	}
       
   154 
       
   155 /**
       
   156 @SYMTestCaseID			PDS-SQLITE3-UT-4029
       
   157 @SYMTestCaseDesc		Sqlite file handle test
       
   158 						The test verifies that a database can be opened from different threads in the same process,
       
   159 						when the shared page cache is enabled. In this case the database file handle is shared between the
       
   160 						threads that open the database.
       
   161 @SYMTestPriority		High
       
   162 @SYMTestActions			Sqlite file handle test
       
   163 @SYMTestExpectedResults Test must not fail
       
   164 @SYMREQ					REQ10424
       
   165 */
       
   166 void FileHandleTest()
       
   167 	{
       
   168 	DeleteFile(KTestDb);
       
   169     sqlite3_enable_shared_cache(1);//this is a per-process setting (was per-thread in SQLite 3.3.17)
       
   170     TInt err = sqlite3_open(KTestDb, &TheDb); 
       
   171 	TEST2(err, SQLITE_OK);
       
   172     
       
   173     err = sqlite3_exec(TheDb, "CREATE TABLE B(Id INTEGER,Name TEXT)", 0, 0, 0);
       
   174 	TEST2(err, SQLITE_OK);
       
   175     err = sqlite3_exec(TheDb, "INSERT INTO B VALUES(1, 'BBB')", 0, 0, 0);
       
   176 	TEST2(err, SQLITE_OK);
       
   177 	
       
   178 	////////////////////////////////////////////////////////////
       
   179 	// The created thread uses the heap of the creating thread
       
   180 	// The same SQLite database can be accessed from different threads in
       
   181 	// shared page cache mode only if the threads share the same heap.
       
   182 	// The database file handle will be shared between threads.
       
   183 	////////////////////////////////////////////////////////////
       
   184 	RDebug::Print(_L("*** Shared heap\r\n"));	
       
   185 	RThread thr;
       
   186     err = thr.Create(_L("TestThr"), &ThreadFunc, KDefaultStackSize, NULL, NULL);
       
   187 	TEST2(err, KErrNone);
       
   188     thr.Resume();
       
   189 	TRequestStatus stat;
       
   190 	thr.Logon(stat);
       
   191 	User::WaitForRequest(stat);
       
   192 	User::SetJustInTime(ETrue);	// enable debugger panic handling
       
   193 	
       
   194 	TInt exitType = thr.ExitType();
       
   195 	TInt exitReason = thr.ExitReason();
       
   196 	thr.Close();
       
   197 	TEST2(exitReason, 0);
       
   198 	TEST2(exitType, EExitKill);
       
   199 	////////////////////////////////////////////////////////////
       
   200 	
       
   201     sqlite3_close(TheDb);
       
   202     TheDb = NULL;
       
   203 	}
       
   204 
       
   205 ///////////////////////////////////////////////////////////////////////////////////////
       
   206 ///////////////         Sqlite3 DLL OOM test         ////////////////////////////////
       
   207 ///////////////////////////////////////////////////////////////////////////////////////
       
   208 
       
   209 /**
       
   210 @SYMTestCaseID			PDS-SQLITE3-CT-4028
       
   211 @SYMTestCaseDesc		Sqlite OOM test 
       
   212 						Precondition: none
       
   213 						A standard OOM test checks the sqlite3 DLL for memory leaks documented 
       
   214 						on the raised defect, to check if the applied fix is working. Before 
       
   215 						the fix the test was failing with PANIC USER:84 on the second iteration 
       
   216 						loop on DoTest()
       
   217 @SYMTestPriority		Medium
       
   218 @SYMTestActions			Sqlite OOM test - 
       
   219 						Opens the database file.						
       
   220 						Calls sqlite3_prepare16_v2()
       
   221 						Closes database
       
   222 						Checks memory leaks
       
   223 						Repeats the above indefinitely until SQLITE_OK
       
   224 @SYMTestExpectedResults Test must not fail
       
   225 @SYMDEF					DEF121506
       
   226 */
       
   227 void DEF121506()
       
   228 	{
       
   229 	RDebug::Print(_L("Iteration: \r\n"));
       
   230 	for (TInt it = 1;  ; ++it)
       
   231 		{
       
   232 		RDebug::Print(_L("%d "), it);
       
   233 		TInt c1 = User::CountAllocCells();
       
   234  		__UHEAP_SETFAIL(RHeap::EDeterministic, it);
       
   235 		
       
   236  		TInt err = sqlite3_open(KTestDb,&TheDb);
       
   237 
       
   238 		if(err == SQLITE_OK)
       
   239 			{
       
   240 	 		sqlite3_stmt* stmt = 0; 
       
   241 	 		const void* tail = 0;	
       
   242 			err = sqlite3_prepare16_v2(TheDb, 
       
   243 						L"CREATE TABLE Sample(Id INTEGER PRIMARY KEY NOT NULL, Name TEXT NOT NULL UNIQUE COLLATE NOCASE);", 
       
   244 						-1, &stmt, &tail);	
       
   245 			(void)sqlite3_finalize(stmt);
       
   246 			}
       
   247  		
       
   248 		(void)sqlite3_close(TheDb);
       
   249 		TheDb = NULL;
       
   250 		__UHEAP_RESET;
       
   251 		
       
   252  		TInt c2 = User::CountAllocCells();
       
   253  		if (c1 != c2)
       
   254 			{	
       
   255 			RDebug::Print(_L("\r\n*** OOM Test failed\r\n"));
       
   256 			TEST(EFalse);
       
   257 			} 		
       
   258  		else if (err == SQLITE_OK) 
       
   259  			{
       
   260  			RDebug::Print(_L("\r\n*** OOM Test passed\r\n"));
       
   261  			break; 			
       
   262  			}
       
   263  		TEST2(err, SQLITE_NOMEM);
       
   264  		}	
       
   265 	}
       
   266 
       
   267 /**
       
   268 @SYMTestCaseID			PDS-SQLITE3-CT-4046
       
   269 @SYMTestCaseDesc		[sqlite3] can't execute sql sequence in transcation. 
       
   270 @SYMTestPriority		High
       
   271 @SYMTestActions			The test deletes the test application private data cage.
       
   272 						Then the test creates a database and attempts to execute a set
       
   273 						of SQL statements, some of them will need a temporary file to be created.
       
   274 						Since the test application private data cage (so the session path) does not exist,
       
   275 						the SQLite OS porting layer will fail to create the requested temporary file and
       
   276 						will fail with KErrPathNotFound error. 
       
   277 						The OS porting layer was fixed to create the session path if the temporary file creation error
       
   278 						is KErrPathNotFound. 
       
   279 @SYMTestExpectedResults Test must not fail
       
   280 @SYMDEF					DEF140020
       
   281 */
       
   282 void DEF140020()
       
   283 	{
       
   284 	//Remove the private data cage
       
   285 	CFileMan* fm = 0;
       
   286 	TRAPD(err, fm = CFileMan::NewL(TheFs));
       
   287 	TEST(fm != 0);
       
   288 	
       
   289 	TFileName privatePath;
       
   290 	err = TheFs.SessionPath(privatePath);
       
   291 	TEST2(err, KErrNone);
       
   292 	err = fm->RmDir(privatePath);
       
   293 	TEST(err == KErrNone || err == KErrPathNotFound);
       
   294 	
       
   295 	delete fm;
       
   296 	fm = 0;
       
   297 
       
   298 	TEST2((TUint)TheDb, 0);
       
   299 	err = sqlite3_open(KTestDb2, &TheDb);
       
   300 	TEST2(err, SQLITE_OK);
       
   301 	
       
   302     const char * stmt[] ={
       
   303             "CREATE TABLE fortest (id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, intcol INTEGER NOT NULL, charcol CHAR(255) ) ",
       
   304             "INSERT INTO fortest(intcol, charcol) VALUES(1,'111');",
       
   305             "BEGIN TRANSACTION;",
       
   306             "CREATE TABLE t1_backup(id INTEGER, intcol INTEGER NOT NULL);",
       
   307             "INSERT INTO t1_backup SELECT id, intcol FROM fortest;",
       
   308             "DROP TABLE fortest;",
       
   309             "CREATE TABLE fortest (id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, intcol INTEGER NOT NULL);",
       
   310             "INSERT INTO fortest(id, intcol) SELECT id,intcol FROM t1_backup;",
       
   311             "DROP TABLE t1_backup;",
       
   312             "select count(*) from fortest;",
       
   313             "COMMIT;",
       
   314             "select count(*) from fortest;",
       
   315             "CREATE TABLE t1_backup(id INTEGER, intcol INTEGER NOT NULL);",
       
   316             "INSERT INTO t1_backup SELECT id, intcol FROM fortest;",
       
   317             "DROP TABLE fortest;",
       
   318             "CREATE TABLE fortest (id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, intcol INTEGER NOT NULL);",
       
   319             "INSERT INTO fortest(id, intcol) SELECT id,intcol FROM t1_backup;",
       
   320             "DROP TABLE t1_backup;",
       
   321             };
       
   322 
       
   323     char* msg = NULL;
       
   324     int i = 0;
       
   325     for (i = 0; i < sizeof(stmt) / sizeof(*stmt); i++)
       
   326         {
       
   327         err = sqlite3_exec(TheDb, stmt[i], NULL, NULL, &msg);
       
   328         TEST2(err, SQLITE_OK);
       
   329         }
       
   330 
       
   331     sqlite3_close(TheDb);
       
   332     TheDb = 0;
       
   333     DeleteFile(KTestDb2);
       
   334 	}
       
   335 
       
   336 /**
       
   337 @SYMTestCaseID          PDS-SQLITE3-CT-4047
       
   338 @SYMTestCaseDesc        Test for DEF143066: SQLITE, "CREATE INDEX" sql crashes the SQLite library.
       
   339                         The test creates a database with one empty table and establishes two connections
       
   340                         to that database. Then, while the first connection is at the middle of a read
       
   341                         transaction, the second connection attempts to create an index.
       
   342                         If the defect is not fixed, the SQLite library will crash.
       
   343 @SYMTestPriority        High
       
   344 @SYMTestActions         DEF143066: SQLITE, "CREATE INDEX" sql crashes the SQLite library.
       
   345 @SYMTestExpectedResults Test must not fail
       
   346 @SYMDEF                 DEF143066
       
   347 */
       
   348 void DEF143066()
       
   349     {
       
   350     DeleteFile(KTestDb);
       
   351     sqlite3_enable_shared_cache(1);
       
   352     int err = sqlite3_open(KTestDb, &TheDb); 
       
   353     TEST2(err, SQLITE_OK);
       
   354     
       
   355     err = sqlite3_exec(TheDb, "CREATE TABLE T0(Thread INTEGER, LocalIndex INTEGER, Inserts INTEGER, Updates INTEGER, IndexMod8 INTEGER)", 0, 0, 0);
       
   356     TEST2(err, SQLITE_OK);
       
   357     
       
   358     err = sqlite3_open(KTestDb, &TheDb2); 
       
   359     TEST2(err, SQLITE_OK);
       
   360 
       
   361     sqlite3_stmt* stmt = 0; 
       
   362     const char* tail = 0;   
       
   363     err = sqlite3_prepare_v2(TheDb, "SELECT COUNT(Thread) FROM T0 WHERE Thread = 0", -1, &stmt, &tail);
       
   364     TEST2(err, SQLITE_OK);
       
   365     
       
   366     err = sqlite3_step(stmt);
       
   367     TEST2(err, SQLITE_ROW);
       
   368 
       
   369     err = sqlite3_exec(TheDb2, "CREATE INDEX T0INDEX ON T0(Thread,IndexMod8)", 0, 0, 0);
       
   370     TEST2(err, SQLITE_LOCKED);
       
   371     
       
   372     (void)sqlite3_finalize(stmt);
       
   373     sqlite3_close(TheDb2);
       
   374     TheDb2 = NULL;
       
   375     sqlite3_close(TheDb);
       
   376     TheDb = NULL;
       
   377     DeleteFile(KTestDb);
       
   378     }
       
   379 
       
   380 /**
       
   381 @SYMTestCaseID          PDS-SQL-CT-4048
       
   382 @SYMTestCaseDesc        Test for DEF143151: SQLite, strftime() returns incorrect result.
       
   383                         The test takes the current universal time (using TTime) 
       
   384                         and the current time retrieved from the SQLite library.
       
   385                         The test compares the times and expects the difference to be no more than
       
   386                         1 second. 
       
   387 @SYMTestPriority        High
       
   388 @SYMTestActions         DEF143151: SQLite, strftime() returns incorrect result
       
   389 @SYMTestExpectedResults Test must not fail
       
   390 @SYMDEF                 DEF143151
       
   391 */
       
   392 void DEF143151()
       
   393     {
       
   394     DeleteFile(KTestDb);
       
   395     int err = sqlite3_open(KTestDb, &TheDb); 
       
   396     TEST2(err, SQLITE_OK);
       
   397 
       
   398     //Home date & time
       
   399     TBuf<50> dtstr1;
       
   400     TTime time;
       
   401     time.UniversalTime();
       
   402     TDateTime dt = time.DateTime();
       
   403     
       
   404     sqlite3_stmt* stmt = 0; 
       
   405     const char* tail = 0;   
       
   406     err = sqlite3_prepare_v2(TheDb, "SELECT strftime('%Y-%m-%d,%H:%M:%S','now')", -1, &stmt, &tail);
       
   407     TEST2(err, SQLITE_OK);
       
   408     err = sqlite3_step(stmt);
       
   409     TEST2(err, SQLITE_ROW);
       
   410     
       
   411     //SQLite date & time
       
   412     const unsigned char* s = sqlite3_column_text(stmt, 0);
       
   413     TEST(s != NULL);
       
   414     TBuf<50> dtstr2;
       
   415     dtstr2.Copy(TPtrC8(s));
       
   416     sqlite3_finalize(stmt);
       
   417 
       
   418     sqlite3_close(TheDb);
       
   419     TheDb = NULL;
       
   420     DeleteFile(KTestDb);
       
   421     
       
   422     dtstr1.Format(_L("%04d-%02d-%02d,%02d:%02d:%02d"), dt.Year(), dt.Month() + 1, dt.Day() + 1, dt.Hour(), dt.Minute(), dt.Second());
       
   423     TheTest.Printf(_L("Universal date&time=\"%S\"\n"), &dtstr1);
       
   424     TheTest.Printf(_L("SQLite    date&time=\"%S\"\n"), &dtstr2);
       
   425     
       
   426     //Comapare and fail if dates are not equal (+- 1 second)
       
   427     TLex lex;
       
   428     lex = dtstr2.Mid(0, 4);
       
   429     TInt sqlyear;
       
   430     err = lex.Val(sqlyear);
       
   431     TEST2(err, KErrNone);
       
   432     
       
   433     lex = dtstr2.Mid(5, 2);
       
   434     TInt sqlmonth;
       
   435     err = lex.Val(sqlmonth);
       
   436     TEST2(err, KErrNone);
       
   437     
       
   438     lex = dtstr2.Mid(8, 2);
       
   439     TInt sqlday;
       
   440     err = lex.Val(sqlday);
       
   441     TEST2(err, KErrNone);
       
   442     
       
   443     lex = dtstr2.Mid(11, 2);
       
   444     TInt sqlhour;
       
   445     err = lex.Val(sqlhour);
       
   446     TEST2(err, KErrNone);
       
   447     
       
   448     lex = dtstr2.Mid(14, 2);
       
   449     TInt sqlminute;
       
   450     err = lex.Val(sqlminute);
       
   451     TEST2(err, KErrNone);
       
   452     
       
   453     lex = dtstr2.Mid(17, 2);
       
   454     TInt sqlsecond;
       
   455     err = lex.Val(sqlsecond);
       
   456     TEST2(err, KErrNone);
       
   457     
       
   458     TDateTime sqldt(sqlyear, (TMonth)(sqlmonth - 1), sqlday - 1, sqlhour, sqlminute, sqlsecond, 0);
       
   459     TTime sqltime(sqldt);
       
   460     TTimeIntervalSeconds diff;
       
   461     err = sqltime.SecondsFrom(time, diff);
       
   462     TEST2(err, KErrNone);
       
   463     TEST(diff.Int() <= 1);
       
   464     }
       
   465 
       
   466 void DoTest()
       
   467 	{
       
   468 	TheTest.Start(_L("@SYMTestCaseID:PDS-SQLITE3-UT-4029: SQLite file handle test"));
       
   469 	FileHandleTest();
       
   470 	
       
   471 	TheTest.Next(_L("@SYMTestCaseID:PDS-SQLITE3-CT-4028: DEF121506 test"));
       
   472 	DEF121506();
       
   473 
       
   474 	TheTest.Next(_L("@SYMTestCaseID:PDS-SQLITE3-CT-4046: DEF140020 test"));
       
   475 	DEF140020();
       
   476 
       
   477     TheTest.Next(_L("@SYMTestCaseID:PDS-SQLITE3-CT-4047: SQLITE, \"CREATE INDEX\" sql crashes the SQLite library"));
       
   478     DEF143066();
       
   479 
       
   480     TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-CT-4048 DEF143151: SQLite, strftime() returns incorrect result"));
       
   481     DEF143151();
       
   482 	}
       
   483 
       
   484 ///////////////////////////////////////////////////////////////////////////////////////
       
   485 
       
   486 TInt E32Main()
       
   487 	{
       
   488 	TheTest.Title();
       
   489 	CTrapCleanup* tc = CTrapCleanup::New();
       
   490 
       
   491 	__UHEAP_MARK;
       
   492 	
       
   493 	CreateTestEnv();
       
   494 	DoTest();
       
   495 	DestroyTestEnv();
       
   496 	
       
   497 	__UHEAP_MARKEND;
       
   498 
       
   499 	TheTest.End();	
       
   500 	TheTest.Close();
       
   501 	delete tc;
       
   502 	User::Heap().Check();
       
   503 	return KErrNone;
       
   504 	}