diff -r 000000000000 -r 08ec8eefde2f persistentstorage/sql/TEST/t_sqldb64.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/sql/TEST/t_sqldb64.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,544 @@ +// Copyright (c) 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 + +/////////////////////////////////////////////////////////////////////////////////////// + +RTest TheTest(_L("t_sqldb64 test")); +RFs TheFs; +RSqlDatabase TheDb; +RSqlStatement TheStmt; + +_LIT(KTestDbName1, "\\test\\t_sqldb64_1.db"); + +const TInt64 K1Mb = 1024LL * 1024LL; +const TInt64 K1Gb = 1024LL * K1Mb; +const TInt64 K4Gb = 4LL * K1Gb; + +TInt64 TheLastInsertedRowid = -1LL; + +struct TTestDriveInfo + { + TInt iSizeMb; + TBool iWritable; + }; + +TTestDriveInfo TheDriveInfo[KMaxDrives]; +TInt TheBiggestDriveNo = -1; +TFileName TheDbName; + +/////////////////////////////////////////////////////////////////////////////////////// + +void DeleteTestFiles() + { + TheStmt.Close(); + TheDb.Close(); + (void)RSqlDatabase::Delete(TheDbName); + } + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +//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() + { + TInt err = TheFs.Connect(); + TEST2(err, KErrNone); + } + +void SqlTimerPrint(const TDesC& aText, TUint32 aStartTicks, TUint32 aEndTicks) + { + static TInt freq = 0; + if(freq == 0) + { + TEST2(HAL::Get(HAL::EFastCounterFrequency, freq), KErrNone); + } + TInt64 diffTicks = (TInt64)aEndTicks - (TInt64)aStartTicks; + if(diffTicks < 0) + { + diffTicks = KMaxTUint32 + diffTicks + 1; + } + const TInt KMicroSecIn1Sec = 1000000; + TInt32 us = (diffTicks * KMicroSecIn1Sec) / freq; + TheTest.Printf(_L("#### %S. Execution time: %d us\r\n"), &aText, us); + } + +TUint32 SqlTimerTicks() + { + return User::FastCounter(); + } + +/////////////////////////////////////////////////////////////////////////////////////// + +/** +@SYMTestCaseID PDS-SQL-CT-4129 +@SYMTestCaseDesc Creation of a database bigger than 4Gb (KMaxTUint). + The test creates a test database with a table and inserts records into the table + until the database size gets bigger than 4Gb (KMaxTUint). The purpose of the test is to verify + that it is possible to create and manipulate 64-bit databases. +@SYMTestActions Creation of a database bigger than 4Gb (KMaxTUint). +@SYMTestExpectedResults Test must not fail +@SYMTestPriority Medium +@SYMREQ REQ12104 + REQ12105 +*/ +void CreateBigDbTest(const TDesC& aDbName, TInt64 aDbSize) + { + __ASSERT_ALWAYS(aDbSize > 0LL, User::Invariant()); + (void)RSqlDatabase::Delete(aDbName); + _LIT8(KConfig, "encoding=\"UTF-8\""); + TInt err = TheDb.Create(aDbName, &KConfig); + TEST2(err, KErrNone); + // + err = TheDb.Exec(_L8("CREATE TABLE A(Id INTEGER PRIMARY KEY AUTOINCREMENT, Data BLOB)")); + TEST2(err, 1); + TInt64 fsize = 0; + TheTest.Printf(_L("==File size:")); + while(fsize < aDbSize) + { + const TInt KRecCnt = 1000; + //Insert KRecCnt records in a transaction + err = TheDb.Exec(_L8("BEGIN")); + if(err < 0) + { + TheTest.Printf(_L("==='BEGIN' has failed with err %d\r\n"), err); + } + TEST(err >= 0); + err = TheStmt.Prepare(TheDb, _L8("INSERT INTO A(Data) VALUES(zeroblob(32768))"));//32Kb big blob + TEST2(err, KErrNone); + for(TInt i=0;i= 0); + TheLastInsertedRowid = TheDb.LastInsertedRowId(); + TEST(TheLastInsertedRowid > 0LL); + //Check and print the file size + TheDb.Close(); + RFile64 file; + err = file.Open(TheFs, aDbName, EFileRead | EFileWrite); + TEST2(err, KErrNone); + err = file.Size(fsize); + TEST2(err, KErrNone); + file.Close(); + TheTest.Printf(_L(" %ldMb"), fsize / K1Mb); + err = TheDb.Open(aDbName); + TEST2(err, KErrNone); + } + TheTest.Printf(_L("\r\n")); + // + TheDb.Close(); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4130 +@SYMTestCaseDesc SQL operations on a 64-bit database. + The test uses the database created in test case PDS-SQL-UT-4129. + Simple INSERT, UPDATE, DELETE and SELECT statements are executed on the database. + The data in the test SQL statements is such that the manipulated records are beyond the 4Gb + file offset. Some other of the test SQL statements will perform sequential scan of the whole + database from offset 0 to the end of the database file. + The purpose of the test is to verify that there are no problem if the database offset is 64-bit. +@SYMTestActions SQL operations on a 64-bit database. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority Medium +@SYMREQ REQ12104 + REQ12105 +*/ +void SimpleDbOperationsTestL(const TDesC& aDbName) + { + __ASSERT_ALWAYS(TheLastInsertedRowid > 0LL, User::Invariant()); + TInt err = TheDb.Open(aDbName); + TEST2(err, KErrNone); + //SELECT-1 + TUint32 start = SqlTimerTicks(); + err = TheStmt.Prepare(TheDb, _L8("SELECT Id FROM A WHERE ROWID = :Prm")); + TEST2(err, KErrNone); + err = TheStmt.BindInt64(0, TheLastInsertedRowid - 1LL); + TEST2(err, KErrNone); + err = TheStmt.Next(); + TEST2(err, KSqlAtRow); + TInt64 id = TheStmt.ColumnInt64(0); + TheTest.Printf(_L("==Id=%ld\r\n"), id); + TheStmt.Close(); + TUint32 end = SqlTimerTicks(); + SqlTimerPrint(_L("SELECT-1"), start, end); + //INSERT + start = SqlTimerTicks(); + err = TheDb.Exec(_L("INSERT INTO A(Data) VALUES('123456')")); + TEST2(err, 1); + end = SqlTimerTicks(); + SqlTimerPrint(_L("INSERT"), start, end); + //UPDATE + start = SqlTimerTicks(); + TBuf<100> sql; + sql.Format(_L("UPDATE A SET Data='56789' WHERE Id=%ld"), id); + err = TheDb.Exec(sql); + TEST2(err, 1); + end = SqlTimerTicks(); + SqlTimerPrint(_L("UPDATE"), start, end); + //SELECT-2 + start = SqlTimerTicks(); + TSqlScalarFullSelectQuery scalarQuery(TheDb); + sql.Format(_L("SELECT Data FROM A WHERE ID = %ld"), id); + TBuf<32> buf; + err = scalarQuery.SelectTextL(sql, buf); + TEST2(err, KErrNone); + err = buf.Compare(_L("56789")); + TEST2(err, 0); + end = SqlTimerTicks(); + SqlTimerPrint(_L("SELECT-2"), start, end); + //SELECT-3 + start = SqlTimerTicks(); + sql.Format(_L("SELECT COUNT(*) FROM A")); + TInt recCnt = scalarQuery.SelectIntL(sql); + TheTest.Printf(_L("==Records count: %d\r\n"), recCnt); + end = SqlTimerTicks(); + SqlTimerPrint(_L("SELECT-3"), start, end); + TEST(recCnt > 0); + //SELECT-4 + start = SqlTimerTicks(); + sql.Format(_L("SELECT MAX(ROWID) FROM A")); + TInt rowid = scalarQuery.SelectIntL(sql); + TheTest.Printf(_L("==MAX(ROWID): %d\r\n"), rowid); + end = SqlTimerTicks(); + SqlTimerPrint(_L("SELECT-4"), start, end); + TEST(rowid > 0); + //DELETE + start = SqlTimerTicks(); + sql.Format(_L("DELETE FROM A WHERE ID = %ld"), id); + err = TheDb.Exec(sql); + TEST2(err, 1); + end = SqlTimerTicks(); + SqlTimerPrint(_L("DELETE"), start, end); + // + TheDb.Close(); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4145 +@SYMTestCaseDesc RSqlDatabase::Size() on a 64-bit database. + The test uses the database created in test case PDS-SQL-UT-4129, opens the database + and calls the Size() methods. The first Size() call should fail with KErrTooBig error, + because the database size is over 2Gb and cannot fit in the 32-bit integer result of the call. + The second call of the overloaded Size() method should correctly report the database size. +@SYMTestActions RSqlDatabase::Size() on a 64-bit database. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority Medium +@SYMREQ REQ12105 +*/ +void SizeTest(const TDesC& aDbName) + { + __ASSERT_ALWAYS(TheLastInsertedRowid > 0LL, User::Invariant()); + TInt err = TheDb.Open(aDbName); + TEST2(err, KErrNone); + //Size-1 + TInt size = TheDb.Size(); + TEST2(size, KErrTooBig); + //Size-2 + RSqlDatabase::TSize size2; + err = TheDb.Size(size2); + TEST2(err, KErrNone); + TEST(size2.iSize > K4Gb); + // + TheDb.Close(); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4146 +@SYMTestCaseDesc Background compaction on a 64-bit database. + The test uses the database created in test case PDS-SQL-UT-4129 and opens the database. + Iteration 1: + The test executes a DELETE sql statement that deletes couple of records. The freed disk space + is big enough to kick-off the background compaction. The test waits couple of seconds and then + checks the database size and free space to verify that the background compaction really compacted + the database. + Iteration 2: + Iteration 2 is the same as iteration 1, but the freed database space is such that the following + background compaction will shrink the database size to be less than 4Gb. + After iteration 2 the test performs an INSERT transaction and increases the database size to be + bigger than 4Gb. +@SYMTestActions Background compaction on a 64-bit database. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority Medium +@SYMREQ REQ12105 +*/ +void BackgroundCompactionTest(const TDesC& aDbName) + { + __ASSERT_ALWAYS(TheLastInsertedRowid > 0LL, User::Invariant()); + TInt err = TheDb.Open(aDbName); + TEST2(err, KErrNone); + const TInt64 KDelRecCnt[2] = {10LL, 2400LL}; + for(TInt i=0;i<2;++i) + { + TheTest.Printf(_L("=========== Iteration %d ===========\r\n"), i + 1); + //Size-1 + RSqlDatabase::TSize size; + err = TheDb.Size(size); + TEST2(err, KErrNone); + TEST(size.iSize > K4Gb); + TheTest.Printf(_L(" ==Before DELETE, database size=%ldKb\r\n"), size.iSize / 1024LL); + //Delete records + TBuf<100> sql; + sql.Format(_L("DELETE FROM A WHERE ROWID > %ld AND ROWID < %ld"), TheLastInsertedRowid - KDelRecCnt[i], TheLastInsertedRowid); + err = TheDb.Exec(sql); + TEST(err > 0); + //Size-2 + err = TheDb.Size(size); + TEST2(err, KErrNone); + TEST(size.iSize > K4Gb); + TEST(size.iFree > (50 * 1024)); + TheTest.Printf(_L(" ==After DELETE, database size=%ldKb, free space=%ldKb\r\n"), size.iSize / 1024LL, size.iFree / 1024LL); + //Wait some time (to allow the background compaction to run) + const TInt KOneSecond = 1000000; + const TInt KMaxWaitTime = 300 * KOneSecond;//300 sec == 5 min + TInt waitTime = 0; + while(waitTime < KMaxWaitTime) + { + const TInt KWaitStep = 5 * KOneSecond; + User::After(KWaitStep); + //Check the size + err = TheDb.Size(size); + TEST2(err, KErrNone); + if(size.iFree == 0) + { + break; + } + waitTime += KWaitStep; + TheTest.Printf(_L(" ==After %3d sec, database size=%ldKb, free space=%ldKb\r\n"), waitTime / KOneSecond, size.iSize / 1024LL, size.iFree / 1024LL); + } + if(i == 0) + { + TEST(size.iSize > K4Gb); + } + else + { + TEST(size.iSize < K4Gb); + } + TEST2(size.iFree, 0); + //Records count + sql.Format(_L("SELECT COUNT(*) FROM A")); + TSqlScalarFullSelectQuery q(TheDb); + TInt recCnt = -1; + TRAP(err, recCnt = q.SelectIntL(sql)); + TEST2(err, KErrNone); + TheTest.Printf(_L(" ==Records count: %d\r\n"), recCnt); + TEST(recCnt > 0); + } + TheTest.Printf(_L("==Increase the database size above 4Gb\r\n")); + //Insert KRecCnt records in a transaction + const TInt KRecCnt = 2500; + err = TheDb.Exec(_L8("BEGIN")); + TEST(err >= 0); + err = TheStmt.Prepare(TheDb, _L8("INSERT INTO A(Data) VALUES(zeroblob(32768))"));//32Kb big blob + TEST2(err, KErrNone); + for(TInt i=0;i= 0); + //Size + RSqlDatabase::TSize size2; + err = TheDb.Size(size2); + TEST2(err, KErrNone); + TEST(size2.iSize > K4Gb); + TheTest.Printf(_L(" ==Database size=%ldKb\r\n"), size2.iSize / 1024LL); + // + TheDb.Close(); + } + +/** +@SYMTestCaseID PDS-SQL-CT-4131 +@SYMTestCaseDesc Deleting database bigger than 4Gb (KMaxTUint). + The test deletes the database created in test case PDS-SQL-UT-4129. +@SYMTestActions Deleting database bigger than 4Gb (KMaxTUint). +@SYMTestExpectedResults Test must not fail +@SYMTestPriority Medium +@SYMREQ REQ12104 + REQ12105 +*/ +void DeleteBigDbTest() + { + TInt err = RSqlDatabase::Delete(TheDbName); + TEST2(err, KErrNone); + } + +void CollectDriveInfo() + { + TheTest.Printf(_L("==================\r\n")); + _LIT(KType1, "Not present"); + _LIT(KType2, "Unknown"); + _LIT(KType3, "Floppy"); + _LIT(KType4, "Hard disk"); + _LIT(KType5, "CD ROM"); + _LIT(KType6, "RAM disk"); + _LIT(KType7, "Flash"); + _LIT(KType8, "ROM drive"); + _LIT(KType9, "Remote drive"); + _LIT(KType10,"NAND flash"); + _LIT(KType11,"Rotating media"); + + Mem::FillZ(TheDriveInfo, sizeof(TheDriveInfo)); + TheBiggestDriveNo = 0; + + for(TInt drive=EDriveA;drive<=EDriveZ;++drive) + { + TDriveInfo driveInfo; + TInt err = TheFs.Drive(driveInfo, drive); + if(err == KErrNone) + { + TVolumeInfo vinfo; + err = TheFs.Volume(vinfo, drive); + if(err == KErrNone) + { + TVolumeIOParamInfo vparam; + err = TheFs.VolumeIOParam(drive, vparam); + TEST2(err, KErrNone); + TBuf8<128> vinfoex8; + err = TheFs.QueryVolumeInfoExt(drive, EFileSystemSubType, vinfoex8); + TEST2(err, KErrNone); + TPtrC vinfoex((const TUint16*)(vinfoex8.Ptr() + 8), vinfoex8[0]); + TPtrC KMediaTypeNames[] = {KType1(), KType2(), KType3(), KType4(), KType5(), KType6(), KType7(), KType8(), KType9(), KType10(), KType11()}; + TInt sizeMb = vinfo.iSize / K1Mb; + TheTest.Printf(_L("Drive: %C:, Type: %16.16S, File System: %8.8S, Size: %d Mb.\r\n"), 'A' + drive, &KMediaTypeNames[driveInfo.iType], &vinfoex, sizeMb); + TheTest.Printf(_L(" Block size=%d, Cluster size=%d, Read buffer size=%d.\r\n"), vparam.iBlockSize, vparam.iClusterSize, vparam.iRecReadBufSize); + TheDriveInfo[drive].iSizeMb = sizeMb; + if(driveInfo.iType == EMediaRam || driveInfo.iType == EMediaHardDisk || driveInfo.iType == EMediaFlash || driveInfo.iType == EMediaNANDFlash) + { + TheDriveInfo[drive].iWritable = ETrue; + if(sizeMb > TheDriveInfo[TheBiggestDriveNo].iSizeMb) + { + TheBiggestDriveNo = drive; + } + } + } + else + { + TheTest.Printf(_L("Drive %C. RFs::Volume() has failed with err=%d.\r\n"), 'A' + drive, err); + } + } + else + { + TheTest.Printf(_L("Drive %C. RFs::Drive() has failed with err=%d.\r\n"), 'A' + drive, err); + } + } + + TheTest.Printf(_L("The biggest R/W drive is: %C, Size: %d Mb\r\n"), 'A' + TheBiggestDriveNo, TheDriveInfo[TheBiggestDriveNo].iSizeMb); + TDriveUnit drvUnit(TheBiggestDriveNo); + TDriveName drvName = drvUnit.Name(); + TParse parse; + parse.Set(KTestDbName1, &drvName, NULL); + TheDbName.Copy(parse.FullName()); + + TRAPD(err, BaflUtils::EnsurePathExistsL(TheFs, TheDbName)); + TEST(err == KErrNone || err == KErrAlreadyExists); + + TheTest.Printf(_L("==================\r\n")); + } + +void DoTestsL() + { + TheTest.Start(_L("Collect drive information")); + CollectDriveInfo(); + + TInt64 maxDrvSize = TheDriveInfo[TheBiggestDriveNo].iSizeMb * K1Mb; + if(maxDrvSize <= K4Gb) + { + TheTest.Printf(_L("There is no drive bigger than 4Gb. The tests won't be executed.\r\n")); + return; + } + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4129 Create database, bigger than 4Gb")); + CreateBigDbTest(TheDbName, K4Gb + 64 * K1Mb); + + TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-CT-4130 64-bit database - simple operations test")); + SimpleDbOperationsTestL(TheDbName); + + TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-CT-4145 64-bit database - Size() test")); + SizeTest(TheDbName); + + TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-CT-4146 64-bit database - background compaction test")); + BackgroundCompactionTest(TheDbName); + + TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-CT-4131 Delete 64-bit database test")); + DeleteBigDbTest(); + } + +TInt E32Main() + { + TheTest.Title(); + + CTrapCleanup* tc = CTrapCleanup::New(); + TheTest(tc != NULL); + + __UHEAP_MARK; + + CreateTestEnv(); + DeleteTestFiles(); + TRAPD(err, DoTestsL()); + DeleteTestFiles(); + TheFs.Close(); + TEST2(err, KErrNone); + + __UHEAP_MARKEND; + + TheTest.End(); + TheTest.Close(); + + delete tc; + + User::Heap().Check(); + return KErrNone; + }