persistentstorage/sqlite3api/TEST/t_sqlitedb64.cpp
changeset 0 08ec8eefde2f
child 55 44f437012c90
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 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 #include <e32test.h>
       
    16 #include <bautils.h>
       
    17 #include <f32file64.h>
       
    18 #include <e32math.h>
       
    19 #include <hal.h>
       
    20 #include <sqlite3.h>
       
    21 #include <string.h>
       
    22 #include <stdio.h>
       
    23 
       
    24 ///////////////////////////////////////////////////////////////////////////////////////
       
    25 
       
    26 RTest TheTest(_L("t_sqlitedb64 test"));
       
    27 
       
    28 _LIT(KTestDbName,	"\\test\\t_sqlitedb64.db");
       
    29 
       
    30 RFs TheFs;
       
    31 
       
    32 sqlite3* TheDb = 0;
       
    33 sqlite3_stmt* TheStmt = 0;
       
    34 
       
    35 const TInt64 K1Mb = 1024LL * 1024LL;
       
    36 const TInt64 K1Gb = 1024LL * K1Mb;
       
    37 const TInt64 K4Gb = 4LL * K1Gb;
       
    38 
       
    39 TInt64 TheLastInsertedRowid = -1LL;
       
    40 
       
    41 struct TTestDriveInfo
       
    42 	{
       
    43 	TInt	iSizeMb;	
       
    44 	TBool	iWritable;	
       
    45 	};
       
    46 	
       
    47 TTestDriveInfo TheDriveInfo[KMaxDrives];
       
    48 TInt   		   TheBiggestDriveNo = -1;
       
    49 TFileName 	   TheDbName;
       
    50 char		   TheDbName8[KMaxFileName];
       
    51 
       
    52 ///////////////////////////////////////////////////////////////////////////////////////
       
    53 
       
    54 static void DeleteTestFiles()
       
    55 	{
       
    56 	if(TheStmt)
       
    57 		{
       
    58 		sqlite3_finalize(TheStmt);	
       
    59 		TheStmt = 0;
       
    60 		}
       
    61 	if(TheDb)
       
    62 		{
       
    63 		(void)sqlite3_close(TheDb);
       
    64 		TheDb = 0;
       
    65 		}
       
    66 	(void)TheFs.Delete(TheDbName);
       
    67 	}
       
    68 
       
    69 ///////////////////////////////////////////////////////////////////////////////////////
       
    70 static void PrintSqliteErrMsg()
       
    71 	{
       
    72 	if(TheDb)
       
    73 		{
       
    74 		const char* msg = sqlite3_errmsg(TheDb);
       
    75 		TBuf<200> buf;
       
    76 		buf.Copy(TPtrC8((const TUint8*)msg));
       
    77 		TheTest.Printf(_L("*** SQLite error message: \"%S\"\r\n"), &buf);
       
    78 		}
       
    79 	}
       
    80 
       
    81 //Test macros and functions
       
    82 static void Check(TInt aValue, TInt aLine)
       
    83 	{
       
    84 	if(!aValue)
       
    85 		{
       
    86 		DeleteTestFiles();
       
    87 		PrintSqliteErrMsg();
       
    88 		TheTest(EFalse, aLine);
       
    89 		}
       
    90 	}
       
    91 static void Check(TInt aValue, TInt aExpected, TInt aLine)
       
    92 	{
       
    93 	if(aValue != aExpected)
       
    94 		{
       
    95 		DeleteTestFiles();
       
    96 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
       
    97 		PrintSqliteErrMsg();
       
    98 		TheTest(EFalse, aLine);
       
    99 		}
       
   100 	}
       
   101 #define TEST(arg) ::Check((arg), __LINE__)
       
   102 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
       
   103 
       
   104 ///////////////////////////////////////////////////////////////////////////////////////
       
   105 
       
   106 void SqlTimerPrint(const TDesC& aText, TUint32 aStartTicks, TUint32 aEndTicks)
       
   107 	{
       
   108 	static TInt freq = 0;
       
   109 	if(freq == 0)
       
   110 		{
       
   111 		TEST2(HAL::Get(HAL::EFastCounterFrequency, freq), KErrNone);
       
   112 		}
       
   113 	TInt64 diffTicks = (TInt64)aEndTicks - (TInt64)aStartTicks;
       
   114 	if(diffTicks < 0)
       
   115 		{
       
   116 		diffTicks = KMaxTUint32 + diffTicks + 1;
       
   117 		}
       
   118 	const TInt KMicroSecIn1Sec = 1000000;
       
   119 	TInt32 us = (diffTicks * KMicroSecIn1Sec) / freq;
       
   120 	TheTest.Printf(_L("#### %S. Execution time: %d us\r\n"), &aText, us);
       
   121 	}
       
   122 
       
   123 TUint32 SqlTimerTicks()
       
   124 	{
       
   125 	return User::FastCounter();
       
   126 	}
       
   127 
       
   128 void CollectDriveInfo()
       
   129 	{
       
   130 	TheTest.Printf(_L("==================\r\n"));
       
   131 	_LIT(KType1, "Not present");
       
   132 	_LIT(KType2, "Unknown");
       
   133 	_LIT(KType3, "Floppy");
       
   134 	_LIT(KType4, "Hard disk");
       
   135 	_LIT(KType5, "CD ROM");
       
   136 	_LIT(KType6, "RAM disk");
       
   137 	_LIT(KType7, "Flash");
       
   138 	_LIT(KType8, "ROM drive");
       
   139 	_LIT(KType9, "Remote drive");
       
   140 	_LIT(KType10,"NAND flash");
       
   141 	_LIT(KType11,"Rotating media");
       
   142 	
       
   143 	Mem::FillZ(TheDriveInfo, sizeof(TheDriveInfo));
       
   144 	TheBiggestDriveNo = 0;
       
   145 	
       
   146 	for(TInt drive=EDriveA;drive<=EDriveZ;++drive)
       
   147 		{
       
   148 		TDriveInfo driveInfo;
       
   149 		TInt err = TheFs.Drive(driveInfo, drive);
       
   150 		if(err == KErrNone)
       
   151 			{
       
   152 			TVolumeInfo vinfo;
       
   153 			err = TheFs.Volume(vinfo, drive);
       
   154 			if(err == KErrNone)
       
   155 				{
       
   156 				TVolumeIOParamInfo vparam;
       
   157 				err = TheFs.VolumeIOParam(drive, vparam);
       
   158 				TEST2(err, KErrNone);
       
   159 				TBuf8<128> vinfoex8;
       
   160 				err = TheFs.QueryVolumeInfoExt(drive, EFileSystemSubType, vinfoex8);
       
   161 				TEST2(err, KErrNone);
       
   162 				TPtrC vinfoex((const TUint16*)(vinfoex8.Ptr() + 8), vinfoex8[0]);
       
   163 				TPtrC KMediaTypeNames[] = {KType1(), KType2(), KType3(), KType4(), KType5(), KType6(), KType7(), KType8(), KType9(), KType10(), KType11()};
       
   164 				TInt sizeMb = vinfo.iSize / K1Mb;
       
   165 				TheTest.Printf(_L("Drive: %C:, Type: %16.16S, File System: %8.8S, Size: %d Mb.\r\n"), 'A' + drive, &KMediaTypeNames[driveInfo.iType], &vinfoex, sizeMb);
       
   166 				TheTest.Printf(_L("       Block size=%d, Cluster size=%d, Read buffer size=%d.\r\n"), vparam.iBlockSize, vparam.iClusterSize, vparam.iRecReadBufSize);
       
   167 				TheDriveInfo[drive].iSizeMb = sizeMb;
       
   168 				if(driveInfo.iType == EMediaRam || driveInfo.iType == EMediaHardDisk || driveInfo.iType == EMediaFlash || driveInfo.iType == EMediaNANDFlash)
       
   169 				  	{
       
   170 					TheDriveInfo[drive].iWritable = ETrue;
       
   171 					if(sizeMb > TheDriveInfo[TheBiggestDriveNo].iSizeMb)
       
   172 						{
       
   173 						TheBiggestDriveNo = drive;
       
   174 						}
       
   175 					}
       
   176 				}
       
   177 			else
       
   178 				{
       
   179 				TheTest.Printf(_L("Drive %C. RFs::Volume() has failed with err=%d.\r\n"), 'A' + drive, err);	
       
   180 				}
       
   181 			}
       
   182 		else
       
   183 			{
       
   184 			TheTest.Printf(_L("Drive %C. RFs::Drive() has failed with err=%d.\r\n"), 'A' + drive, err);	
       
   185 			}
       
   186 		}
       
   187 		
       
   188 	TheTest.Printf(_L("The biggest R/W drive is: %C, Size: %d Mb\r\n"), 'A' + TheBiggestDriveNo, TheDriveInfo[TheBiggestDriveNo].iSizeMb);
       
   189 	TDriveUnit drvUnit(TheBiggestDriveNo);
       
   190 	TDriveName drvName = drvUnit.Name();
       
   191 	TParse parse;
       
   192 	parse.Set(KTestDbName, &drvName, NULL);
       
   193 	TheDbName.Copy(parse.FullName());
       
   194 	TPtr8 p((TUint8*)TheDbName8, 0, KMaxFileName);
       
   195 	p.Copy(TheDbName);
       
   196 	p.Append(TChar(0));
       
   197 
       
   198 	TRAPD(err, BaflUtils::EnsurePathExistsL(TheFs, TheDbName));
       
   199 	TEST(err == KErrNone || err == KErrAlreadyExists);
       
   200 
       
   201 	TheTest.Printf(_L("==================\r\n"));
       
   202 	}
       
   203 
       
   204 ///////////////////////////////////////////////////////////////////////////////////////
       
   205 
       
   206 /**
       
   207 @SYMTestCaseID			PDS-SQLITE3-CT-4041
       
   208 @SYMTestCaseDesc		Creation of a database bigger than 4Gb (KMaxTUint).
       
   209 						The test creates a test database with a table and inserts records into the table
       
   210 						until the database size gets bigger than 4Gb (KMaxTUint). The purpose of the test is to verify
       
   211 						that it is possible to create and manipulate 64-bit SQLite databases.
       
   212 @SYMTestActions			Creation of a database bigger than 4Gb (KMaxTUint).
       
   213 @SYMTestExpectedResults Test must not fail
       
   214 @SYMTestPriority 	    High
       
   215 @SYMREQ					REQ12107
       
   216                         REQ12108
       
   217 */
       
   218 void CreateBigDbTest(TInt64 aDbSize)
       
   219 	{
       
   220 	__ASSERT_ALWAYS(aDbSize > 0LL, User::Invariant());
       
   221 	(void)TheFs.Delete(TheDbName);
       
   222 
       
   223 	const char* ver = sqlite3_libversion();
       
   224 	TBuf<20> buf;
       
   225 	buf.Copy(TPtrC8((const TUint8*)ver));
       
   226 	TheTest.Printf(_L("*** SQLite library version: \"%S\"\r\n"), &buf);
       
   227 	
       
   228 	TInt err = sqlite3_open(TheDbName8, &TheDb);
       
   229 	TEST2(err, SQLITE_OK);
       
   230 	
       
   231 	//
       
   232 	err = sqlite3_exec(TheDb, "CREATE TABLE A(Id INTEGER PRIMARY KEY AUTOINCREMENT, Data BLOB)", 0, 0, 0);
       
   233 	TEST2(err, SQLITE_OK);
       
   234 	TInt64 fsize = 0;
       
   235 	TheTest.Printf(_L("==File size:"));
       
   236 	while(fsize < aDbSize)
       
   237 		{
       
   238 		const TInt KRecCnt = 1000;
       
   239 		//Insert KRecCnt records in a transaction
       
   240 		err = sqlite3_exec(TheDb, "BEGIN", 0, 0, 0);	
       
   241 		if(err != SQLITE_OK)
       
   242 			{
       
   243 			TheTest.Printf(_L("==='BEGIN' has failed with err %d\r\n"), err);
       
   244 			}
       
   245 		TEST2(err, SQLITE_OK);
       
   246 		err = sqlite3_prepare(TheDb, "INSERT INTO A(Data) VALUES(zeroblob(32768))", -1, &TheStmt, 0);//32Kb big blob
       
   247 		TEST2(err, SQLITE_OK);
       
   248 		for(TInt i=0;i<KRecCnt;++i)
       
   249 			{
       
   250 			err = sqlite3_step(TheStmt);
       
   251 			TEST2(err, SQLITE_DONE);
       
   252 			err = sqlite3_reset(TheStmt);
       
   253 			TEST2(err, SQLITE_OK);
       
   254 			}
       
   255 		err = sqlite3_finalize(TheStmt);
       
   256 		TEST2(err, SQLITE_OK);
       
   257 		TheStmt = 0;
       
   258 		err = sqlite3_exec(TheDb, "COMMIT", 0, 0, 0);	
       
   259 		if(err != SQLITE_OK)
       
   260 			{
       
   261 			TheTest.Printf(_L("==='COMMIT' has failed with err %d\r\n"), err);	
       
   262 			}
       
   263 		TEST2(err, SQLITE_OK);
       
   264 		TheLastInsertedRowid = sqlite3_last_insert_rowid(TheDb);
       
   265 		TEST(TheLastInsertedRowid > 0LL);
       
   266 		//Check and print the file size
       
   267 		sqlite3_close(TheDb);
       
   268 		TheDb = 0;
       
   269 		RFile64 file;
       
   270 		err = file.Open(TheFs, TheDbName, EFileRead | EFileWrite);
       
   271 		TEST2(err, KErrNone);
       
   272 		err = file.Size(fsize);
       
   273 		TEST2(err, KErrNone);
       
   274 		file.Close();
       
   275 		TheTest.Printf(_L(" %ldMb"), fsize / K1Mb);
       
   276 		err = sqlite3_open(TheDbName8, &TheDb);
       
   277 		TEST2(err, SQLITE_OK);
       
   278 		}
       
   279 	TheTest.Printf(_L("\r\n"));
       
   280 	//
       
   281 	sqlite3_close(TheDb);
       
   282 	TheDb = 0;
       
   283 	}
       
   284 
       
   285 /**
       
   286 @SYMTestCaseID			PDS-SQLITE3-CT-4042
       
   287 @SYMTestCaseDesc		SQLite operations on a 64-bit database.
       
   288 						The test uses the database created in test case PDS-SQLITE3-UT-4041.
       
   289 						Simple INSERT, UPDATE, DELETE and SELECT statements are executed on the database.
       
   290 						The data in the test SQL statements is such that the manipulated records are beyond the 4Gb
       
   291 						file offset. Some other of the test SQL statements will perform sequential scan of the whole
       
   292 						database from offset 0 to the end of the database file.
       
   293 						The purpose of the test is to verify that there are no problem if the database offset is 64-bit.
       
   294 @SYMTestActions			SQLite operations on a 64-bit database.
       
   295 @SYMTestExpectedResults Test must not fail
       
   296 @SYMTestPriority 	    High
       
   297 @SYMREQ					REQ12107
       
   298                         REQ12108
       
   299 */
       
   300 void SimpleDbOperationsTest()
       
   301 	{
       
   302 	__ASSERT_ALWAYS(TheLastInsertedRowid > 0LL, User::Invariant());
       
   303 	TInt err = sqlite3_open(TheDbName8, &TheDb);
       
   304 	TEST2(err, SQLITE_OK);
       
   305 
       
   306 	//SELECT-1
       
   307 	TUint32 start = SqlTimerTicks();
       
   308 	err = sqlite3_prepare(TheDb, "SELECT Id FROM A WHERE ROWID = :Prm", -1, &TheStmt, 0);
       
   309 	TEST2(err, SQLITE_OK);
       
   310 	err = sqlite3_bind_int64(TheStmt, 1, TheLastInsertedRowid - 1LL);
       
   311 	TEST2(err, SQLITE_OK);
       
   312 	err = sqlite3_step(TheStmt);
       
   313 	TEST2(err, SQLITE_ROW);
       
   314 	TInt64 id = sqlite3_column_int64(TheStmt, 0);
       
   315 	TheTest.Printf(_L("==Id=%ld\r\n"), id);
       
   316 	sqlite3_finalize(TheStmt);
       
   317 	TheStmt = 0;
       
   318 	TUint32 end = SqlTimerTicks();
       
   319 	SqlTimerPrint(_L("SELECT-1"), start, end);
       
   320 
       
   321 	//INSERT
       
   322 	start = SqlTimerTicks();
       
   323 	err = sqlite3_exec(TheDb, "INSERT INTO A(Data) VALUES('123456')", 0, 0, 0);
       
   324 	TEST2(err, SQLITE_OK);
       
   325 	end = SqlTimerTicks();
       
   326 	TInt cnt = sqlite3_changes(TheDb);
       
   327 	TEST2(cnt, 1);
       
   328 	SqlTimerPrint(_L("INSERT"), start, end);
       
   329 	
       
   330 	//UPDATE
       
   331 	start = SqlTimerTicks();
       
   332 	TBuf<100> sql;
       
   333 	sql.Format(_L("UPDATE A SET Data='56789' WHERE Id=%ld"), id);
       
   334 	TBuf8<100> sql8;
       
   335 	sql8.Copy(sql);
       
   336 	err = sqlite3_exec(TheDb, (const char*)sql8.PtrZ(), 0, 0, 0);
       
   337 	TEST2(err, SQLITE_OK);
       
   338 	end = SqlTimerTicks();
       
   339 	cnt = sqlite3_changes(TheDb);
       
   340 	TEST2(cnt, 1);
       
   341 	SqlTimerPrint(_L("UPDATE"), start, end);
       
   342 	
       
   343 	//SELECT-2
       
   344 	start = SqlTimerTicks();
       
   345 	sql.Format(_L("SELECT Data FROM A WHERE ID = %ld"), id);
       
   346 	sql8.Copy(sql);
       
   347 	err = sqlite3_prepare(TheDb, (const char*)sql8.PtrZ(), -1, &TheStmt, 0);
       
   348 	TEST2(err, SQLITE_OK);
       
   349 	err = sqlite3_step(TheStmt);
       
   350 	TEST2(err, SQLITE_ROW);
       
   351 	const char* data = (const char*)sqlite3_column_text(TheStmt, 0);
       
   352 	TEST(data != 0);
       
   353 	err = strcmp(data, "56789");
       
   354 	TEST2(err, 0);
       
   355 	sqlite3_finalize(TheStmt);
       
   356 	TheStmt = 0;
       
   357 	end = SqlTimerTicks();
       
   358 	SqlTimerPrint(_L("SELECT-2"), start, end);
       
   359 	
       
   360 	//SELECT-3
       
   361 	start = SqlTimerTicks();
       
   362 	err = sqlite3_prepare(TheDb, "SELECT COUNT(*) FROM A", -1, &TheStmt, 0);
       
   363 	TEST2(err, SQLITE_OK);
       
   364 	err = sqlite3_step(TheStmt);
       
   365 	TEST2(err, SQLITE_ROW);
       
   366 	TInt recCnt = sqlite3_column_int(TheStmt, 0);
       
   367 	TheTest.Printf(_L("==Records count: %d\r\n"), recCnt);
       
   368 	sqlite3_finalize(TheStmt);
       
   369 	TheStmt = 0;
       
   370 	end = SqlTimerTicks();
       
   371 	SqlTimerPrint(_L("SELECT-3"), start, end);
       
   372 	TEST(recCnt > 0);
       
   373 
       
   374 	//SELECT-4
       
   375 	start = SqlTimerTicks();
       
   376 	err = sqlite3_prepare(TheDb, "SELECT MAX(ROWID) FROM A", -1, &TheStmt, 0);
       
   377 	TEST2(err, SQLITE_OK);
       
   378 	err = sqlite3_step(TheStmt);
       
   379 	TEST2(err, SQLITE_ROW);
       
   380 	TInt rowid = sqlite3_column_int(TheStmt, 0);
       
   381 	TheTest.Printf(_L("==MAX(ROWID): %d\r\n"), recCnt);
       
   382 	sqlite3_finalize(TheStmt);
       
   383 	TheStmt = 0;
       
   384 	end = SqlTimerTicks();
       
   385 	SqlTimerPrint(_L("SELECT-4"), start, end);
       
   386 	TEST(rowid > 0);
       
   387 	
       
   388 	//DELETE
       
   389 	start = SqlTimerTicks();
       
   390 	sql.Format(_L("DELETE FROM A WHERE ID = %ld"), id);
       
   391 	sql8.Copy(sql);
       
   392 	err = sqlite3_exec(TheDb, (const char*)sql8.PtrZ(), 0, 0, 0);
       
   393 	TEST2(err, SQLITE_OK);
       
   394 	end = SqlTimerTicks();
       
   395 	cnt = sqlite3_changes(TheDb);
       
   396 	TEST2(cnt, 1);
       
   397 	SqlTimerPrint(_L("DELETE"), start, end);
       
   398 	
       
   399 	sqlite3_close(TheDb);
       
   400 	TheDb = 0;
       
   401 	}
       
   402 
       
   403 ///////////////////////////////////////////////////////////////////////////////////////
       
   404 
       
   405 static void DoTests()
       
   406 	{
       
   407 	TheTest.Start(_L("Collect drive information"));
       
   408 	CollectDriveInfo();
       
   409 	
       
   410 	TInt64 maxDrvSize = TheDriveInfo[TheBiggestDriveNo].iSizeMb * K1Mb;
       
   411 	if(maxDrvSize <= K4Gb)
       
   412 		{
       
   413 		TheTest.Printf(_L("There is no drive bigger than 4Gb. The tests won't be executed.\r\n"));
       
   414 		return;	
       
   415 		}
       
   416 	
       
   417 	TheTest.Next(_L(" @SYMTestCaseID:PDS-SQLITE3-CT-4041 Create database, bigger than 4Gb"));
       
   418 	CreateBigDbTest(K4Gb + 64 * K1Mb);
       
   419 
       
   420 	TheTest.Next (_L("  @SYMTestCaseID:PDS-SQLITE3-CT-4042 64-bit database - simple operations test"));
       
   421 	SimpleDbOperationsTest();
       
   422 
       
   423 	(void)TheFs.Delete(TheDbName);
       
   424 	}
       
   425 
       
   426 TInt E32Main()
       
   427 	{
       
   428 	TheTest.Title();
       
   429 
       
   430 	CTrapCleanup* tc = CTrapCleanup::New();
       
   431 	TheTest(tc != NULL);
       
   432 
       
   433 	__UHEAP_MARK;
       
   434 
       
   435 	TInt err = TheFs.Connect();
       
   436 	TheTest(err == KErrNone);
       
   437 
       
   438 	DeleteTestFiles();
       
   439 	DoTests();
       
   440 	DeleteTestFiles();
       
   441 
       
   442 	__UHEAP_MARKEND;
       
   443 
       
   444 	TheFs.Close();
       
   445 	TheTest.End();
       
   446 	TheTest.Close();
       
   447 
       
   448 	delete tc;
       
   449 
       
   450 	User::Heap().Check();
       
   451 	return KErrNone;
       
   452 	}