persistentstorage/sql/TEST/t_sqlcompact2.cpp
changeset 0 08ec8eefde2f
child 16 6b6fd149daa2
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 #include <f32file.h>
       
    17 #include <e32test.h>
       
    18 #include <hal.h>
       
    19 #include <stdlib.h>
       
    20 #include <sqldb.h>
       
    21 #include "sqlite3.h"
       
    22 #include "SqliteSymbian.h"
       
    23 #include "SqlSrvStatementUtil.h"
       
    24 #include "SqlPanic.h"
       
    25 #include "SqlCompact.h"
       
    26 #include "SqlCompactConn.h"
       
    27 #include "SqlCompactEntry.h"
       
    28 
       
    29 const TInt KOperationCount = 20;
       
    30 const TInt KFreePageThresholdKb = 5;
       
    31 const TInt KFreePageThreshold = 5;
       
    32 
       
    33 const TInt KCompactStepInterval = 5;//ms
       
    34 
       
    35 TSqlCompactSettings TheCompactionSettings;
       
    36 
       
    37 static RTest 			TheTest(_L ("t_sqlcompact2.exe"));
       
    38 static CTrapCleanup*	TheTrapCleanup = NULL;
       
    39 static RFs 				TheFs;
       
    40 static TBuf<KMaxFileName + 1> TheFileNameZ;
       
    41 static TBuf8<KMaxFileName + 1> TheFileNameZ8;
       
    42 
       
    43 const TInt KBlobMaxSize = 1024 * 32;
       
    44 static TBuf8<KBlobMaxSize> TheBlob;
       
    45 
       
    46 static sqlite3* 		TheDbHandle = NULL;
       
    47 
       
    48 _LIT8(KFreePageCountPragma, "PRAGMA freelist_count\x0");
       
    49 
       
    50 TBuf<256>  TheCmd;
       
    51 TDriveName TheDriveName;
       
    52 TParse     TheParse;
       
    53 TFileName  TheDbName;
       
    54 
       
    55 class CSqlCompactTestActive;
       
    56 CSqlCompactTestActive* TheTestActive = NULL;
       
    57 
       
    58 const TTimeIntervalMicroSeconds32 KInterval(200000);
       
    59 
       
    60 static TInt TheProcessHandleCount = 0;
       
    61 static TInt TheThreadHandleCount = 0;
       
    62 static TInt TheAllocatedCellsCount = 0;
       
    63 
       
    64 #ifdef _DEBUG
       
    65 const TInt KBurstRate = 100;
       
    66 #endif
       
    67 
       
    68 //////////////////////////////////////////////////////////////////////////////////////////////////
       
    69 
       
    70 void DeleteTestFiles()
       
    71 	{
       
    72 	::CloseDbHandle(TheDbHandle);
       
    73 	(void)TheFs.Delete(TheDbName);
       
    74 	}
       
    75 
       
    76 ///////////////////////////////////////////////////////////////////////////////////////
       
    77 //Test macros and functions
       
    78 void Check(TInt aValue, TInt aLine)
       
    79 	{
       
    80 	if(!aValue)
       
    81 		{
       
    82 		DeleteTestFiles();
       
    83 		TheTest(EFalse, aLine);
       
    84 		}
       
    85 	}
       
    86 void Check(TInt aValue, TInt aExpected, TInt aLine)
       
    87 	{
       
    88 	if(aValue != aExpected)
       
    89 		{
       
    90 		DeleteTestFiles();
       
    91 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
       
    92 		TheTest(EFalse, aLine);
       
    93 		}
       
    94 	}
       
    95 #define TEST(arg) ::Check((arg), __LINE__)
       
    96 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
       
    97 
       
    98 //////////////////////////////////////////////////////////////////////////////////////////////////
       
    99 
       
   100 void TestEnvCreate()
       
   101 	{	
       
   102 	TInt err = sqlite3SymbianLibInit();
       
   103 	__ASSERT_ALWAYS(err == KErrNone, User::Invariant());
       
   104 	TheFs = sqlite3SymbianFs();
       
   105 	for(TInt i=0;i<('Z'-'A');++i)
       
   106 		{
       
   107 		TheFs.CreatePrivatePath(i);
       
   108 		}
       
   109 	err = TheFs.MkDir(TheDbName);
       
   110 	TEST(err == KErrNone || err == KErrAlreadyExists);
       
   111 	DeleteTestFiles();
       
   112 	}
       
   113 
       
   114 void TestEnvDestroy()
       
   115 	{
       
   116 	DeleteTestFiles();
       
   117 	sqlite3SymbianLibFinalize();
       
   118 	CloseSTDLIB();
       
   119 	}
       
   120 
       
   121 //////////////////////////////////////////////////////////////////////////////////////////////////
       
   122 
       
   123 void MarkHandles()
       
   124 	{
       
   125 	RThread().HandleCount(TheProcessHandleCount, TheThreadHandleCount);
       
   126 	}
       
   127 	
       
   128 void MarkAllocatedCells()
       
   129 	{
       
   130 	TheAllocatedCellsCount = User::CountAllocCells();
       
   131 	}
       
   132 
       
   133 void CheckHandles()
       
   134 	{
       
   135 	TInt processHandleCount = 0;
       
   136 	TInt threadHandleCount = 0;
       
   137 
       
   138 	RThread().HandleCount(processHandleCount, threadHandleCount);
       
   139 
       
   140 	TEST(processHandleCount == TheProcessHandleCount);
       
   141 	TEST(threadHandleCount == TheThreadHandleCount);
       
   142 	}
       
   143 	
       
   144 void CheckAllocatedCells()
       
   145 	{
       
   146 	TInt allocatedCellsCount = User::CountAllocCells();
       
   147 	TEST(allocatedCellsCount == TheAllocatedCellsCount);
       
   148 	}
       
   149 		
       
   150 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   151 
       
   152 const TDesC& FileNameZ(const TDesC& aFileName)
       
   153 	{
       
   154 	TheFileNameZ.Copy(aFileName);
       
   155 	TheFileNameZ.ZeroTerminate();
       
   156 	return TheFileNameZ;
       
   157 	}
       
   158 
       
   159 const TDesC8& FileNameZ8(const TDesC& aFileName)
       
   160 	{
       
   161 	TheFileNameZ8.Copy(aFileName);
       
   162 	TheFileNameZ8.ZeroTerminate();
       
   163 	return TheFileNameZ8;
       
   164 	}
       
   165 
       
   166 TInt FreePageCount()
       
   167 	{
       
   168 	sqlite3_stmt* stmtHandle = NULL;
       
   169 	TInt err = ::StmtPrepare8(TheDbHandle, KFreePageCountPragma, stmtHandle);
       
   170 	TEST2(err, KErrNone);
       
   171 	TEST(stmtHandle != NULL);
       
   172 	err = ::StmtNext(stmtHandle);
       
   173 	TEST2(err, KSqlAtRow);
       
   174 	TInt pageCount = sqlite3_column_int(stmtHandle, 0);
       
   175 	TEST(pageCount >= 0);
       
   176 	::FinalizeStmtHandle(stmtHandle);
       
   177 	return pageCount;
       
   178 	}
       
   179 
       
   180 void PrintInfo(TInt aProcessedPages, const TDesC& aMediaTypeName, TUint32 aStartTicks, TUint32 aEndTicks)
       
   181 	{
       
   182 	static TInt freq = 0;
       
   183 	if(freq == 0)
       
   184 		{
       
   185 		TEST2(HAL::Get(HAL::EFastCounterFrequency, freq), KErrNone);
       
   186 		}
       
   187 	TInt64 diffTicks = (TInt64)aEndTicks - (TInt64)aStartTicks;
       
   188 	if(diffTicks < 0)
       
   189 		{
       
   190 		diffTicks = KMaxTUint32 + diffTicks + 1;
       
   191 		}
       
   192 	const TInt KMicroSecIn1Sec = 1000000;
       
   193 	TInt32 us = (diffTicks * KMicroSecIn1Sec) / freq;
       
   194 	TheTest.Printf(_L("####Media type: %S. Processed pages: %d. Ticks: %ld. Execution time: %d ms\r\n"), 
       
   195 							&aMediaTypeName, aProcessedPages, diffTicks, us / 1000);
       
   196 	}
       
   197 
       
   198 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   199 //////////////////////////////        CSqlCompactTestActive declaration              /////////////////////////////////////////////
       
   200 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   201 
       
   202 class CSqlCompactTestActive : public CActive
       
   203 	{
       
   204 private:
       
   205 	enum TCommand
       
   206 		{
       
   207 		ECmdInvalidTest,	
       
   208 		ECmdBeginTest1,
       
   209 		ECmdEndTest1,
       
   210 		ECmdBeginTest2,
       
   211 		ECmdEndTest2,
       
   212 		ECmdBeginTest3,
       
   213 		ECmdEndTest3,
       
   214 		ECmdStopTests	
       
   215 		};
       
   216 	
       
   217 public:
       
   218 	static void New();
       
   219 	virtual ~CSqlCompactTestActive();
       
   220 	void OomTest();
       
   221 	void FileIoErrTest();
       
   222 	void PerformanceTest();
       
   223 	
       
   224 protected:		
       
   225 	virtual void DoCancel();
       
   226 	virtual void RunL();
       
   227 	virtual TInt RunError(TInt aError);
       
   228 	
       
   229 private:
       
   230 	CSqlCompactTestActive();
       
   231 	void Complete(TCommand aNextCommand);
       
   232 	void Schedule(TCommand aNextCommand, TTimeIntervalMicroSeconds32 aInterval);
       
   233 
       
   234 	void CreateTestDatabase();
       
   235 	void InsertTestRecords(TInt aOpCount = KOperationCount);
       
   236 	void UpdateTestRecords(TInt aOpCount = KOperationCount);
       
   237 	void DeleteTestRecords(TInt aOpCount = KOperationCount);
       
   238 	void DeleteTestRecords2();
       
   239 	void TestEnd();
       
   240 	
       
   241 	void UpdateTestBegin();
       
   242 	void UpdateTestEnd();
       
   243 	void DeleteTestBegin();
       
   244 	void DeleteTestEnd();
       
   245 	void SingleOpCompactTestBegin();
       
   246 	void SingleOpCompactTestEnd();
       
   247 
       
   248 	void DoOomTest1();
       
   249 	void DoOomTest2();
       
   250 	void DoOomTest3();
       
   251 	void DoOomTest4();
       
   252 	void DoOomTest5();
       
   253 
       
   254 private:
       
   255 	TInt			iCommand;
       
   256 	CSqlCompactor*	iCompactor;
       
   257 	RTimer			iTimer;
       
   258 
       
   259 	};
       
   260 
       
   261 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   262 //////////////////////////////        CSqlCompactTestActive implementation             ///////////////////////////////////////////
       
   263 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   264 
       
   265 void CSqlCompactTestActive::New()
       
   266 	{
       
   267 	TheTestActive = new CSqlCompactTestActive;
       
   268 	TEST(TheTestActive != NULL);
       
   269 	}
       
   270 
       
   271 CSqlCompactTestActive::~CSqlCompactTestActive()
       
   272 	{
       
   273 	Cancel();
       
   274 	iTimer.Close();
       
   275 	delete iCompactor;
       
   276 	}
       
   277 	
       
   278 void CSqlCompactTestActive::DoCancel()
       
   279 	{
       
   280 	iTimer.Cancel();
       
   281 	TRequestStatus* stat = &iStatus;
       
   282 	User::RequestComplete(stat, KErrNone);
       
   283 	}
       
   284 	
       
   285 void CSqlCompactTestActive::RunL()
       
   286 	{
       
   287 	switch(iCommand)
       
   288 		{
       
   289 		case CSqlCompactTestActive::ECmdBeginTest1:
       
   290 			TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4053 Update test"));
       
   291 			UpdateTestBegin();
       
   292 			Schedule(CSqlCompactTestActive::ECmdEndTest1, KInterval);
       
   293 			break;
       
   294 		case CSqlCompactTestActive::ECmdEndTest1:
       
   295 			UpdateTestEnd();
       
   296 			Complete(CSqlCompactTestActive::ECmdBeginTest2);
       
   297 			break;
       
   298 		case CSqlCompactTestActive::ECmdBeginTest2:
       
   299 			TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4054 Delete test"));
       
   300 			DeleteTestBegin();
       
   301 			Schedule(CSqlCompactTestActive::ECmdEndTest2, KInterval);
       
   302 			break;
       
   303 		case CSqlCompactTestActive::ECmdEndTest2:
       
   304 			DeleteTestEnd();
       
   305 			Complete(CSqlCompactTestActive::ECmdBeginTest3);
       
   306 			break;
       
   307 		case CSqlCompactTestActive::ECmdBeginTest3:
       
   308 			TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4055 Single operation - compaction test"));
       
   309 			SingleOpCompactTestBegin();
       
   310 			Schedule(CSqlCompactTestActive::ECmdEndTest3, KInterval);
       
   311 			break;
       
   312 		case CSqlCompactTestActive::ECmdEndTest3:
       
   313 			SingleOpCompactTestEnd();
       
   314 			Complete(CSqlCompactTestActive::ECmdStopTests);
       
   315 			break;
       
   316 		case CSqlCompactTestActive::ECmdStopTests:
       
   317 			CActiveScheduler::Stop();
       
   318 			break;
       
   319 		case CSqlCompactTestActive::ECmdInvalidTest:
       
   320 		default:
       
   321 			TEST(0);
       
   322 			break;
       
   323 		}
       
   324 	}
       
   325 
       
   326 TInt CSqlCompactTestActive::RunError(TInt aError)
       
   327 	{
       
   328 	TEST2(aError, KErrNone);
       
   329 	return aError;
       
   330 	}
       
   331 
       
   332 CSqlCompactTestActive::CSqlCompactTestActive() :
       
   333 	CActive(CActive::EPriorityStandard),
       
   334 	iCommand(CSqlCompactTestActive::ECmdInvalidTest),
       
   335 	iCompactor(NULL)
       
   336 	{
       
   337 	TInt err = sqlite3_enable_shared_cache(1);
       
   338 	TEST2(err, SQLITE_OK);
       
   339 	TRAP(err, iCompactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
       
   340 	TEST2(err, KErrNone);
       
   341 	err = iTimer.CreateLocal();
       
   342 	TEST2(err, KErrNone);
       
   343 	CActiveScheduler::Add(this);
       
   344 	Complete(CSqlCompactTestActive::ECmdBeginTest1);
       
   345 	}
       
   346 
       
   347 void CSqlCompactTestActive::Complete(CSqlCompactTestActive::TCommand aNextCommand)
       
   348 	{
       
   349 	TEST(!IsActive());
       
   350 	iCommand = aNextCommand;
       
   351 	TRequestStatus* stat = &iStatus;
       
   352 	User::RequestComplete(stat, KErrNone);
       
   353 	SetActive();	
       
   354 	}
       
   355 
       
   356 void CSqlCompactTestActive::Schedule(TCommand aNextCommand, TTimeIntervalMicroSeconds32 aInterval)
       
   357 	{
       
   358 	TEST(!IsActive());
       
   359 	iCommand = aNextCommand;
       
   360 	iTimer.After(iStatus, aInterval);
       
   361 	TEST2(iStatus.Int(), KRequestPending);
       
   362 	SetActive();
       
   363 	}
       
   364 
       
   365 void CSqlCompactTestActive::CreateTestDatabase()
       
   366 	{
       
   367 	TInt err = ::CreateDbHandle8(::FileNameZ8(TheDbName), TheDbHandle);
       
   368 	TEST2(err, KErrNone);
       
   369 	_LIT8(KCreateTableSql, "CREATE TABLE A(I INTEGRER, B BLOB)\x0");
       
   370 	err = ::DbExecStmt8(TheDbHandle, KCreateTableSql);
       
   371 	TEST2(err, KErrNone);
       
   372 	}
       
   373 
       
   374 void CSqlCompactTestActive::InsertTestRecords(TInt aOpCount)
       
   375 	{
       
   376 	TheBlob.SetLength(SQLITE_DEFAULT_PAGE_SIZE);
       
   377 	for(TInt i=0;i<aOpCount;++i)
       
   378 		{
       
   379 		_LIT8(KInsertSql, "INSERT INTO A VALUES(%d, :Prm)\x0");
       
   380 		TBuf8<sizeof(KInsertSql) + 10> sqlBuf1;
       
   381 		sqlBuf1.Format(KInsertSql, i + 1);
       
   382 		sqlite3_stmt* stmtHandle = NULL;
       
   383 		TInt err = ::StmtPrepare8(TheDbHandle, sqlBuf1, stmtHandle);
       
   384 		TEST2(err, KErrNone);
       
   385 		TEST(stmtHandle != NULL);
       
   386 		err = sqlite3_bind_blob(stmtHandle, 1, TheBlob.Ptr(), SQLITE_DEFAULT_PAGE_SIZE, SQLITE_STATIC);
       
   387 		TEST2(err, SQLITE_OK);
       
   388 		err = ::StmtExec(stmtHandle);
       
   389 		TEST2(err, KErrNone);
       
   390 		::FinalizeStmtHandle(stmtHandle);
       
   391 		}
       
   392 	}
       
   393 
       
   394 void CSqlCompactTestActive::UpdateTestRecords(TInt aOpCount)
       
   395 	{
       
   396 	for(TInt i=0;i<aOpCount;++i)
       
   397 		{
       
   398 		_LIT8(KUpdateSql, "UPDATE A SET B=x'1122' WHERE I=%d\x0");
       
   399 		TBuf8<sizeof(KUpdateSql) + 10> sqlBuf2;
       
   400 		sqlBuf2.Format(KUpdateSql, i + 1);
       
   401 		TInt err = ::DbExecStmt8(TheDbHandle, sqlBuf2);
       
   402 		TEST2(err, KErrNone);
       
   403 		}
       
   404 	}
       
   405 
       
   406 void CSqlCompactTestActive::DeleteTestRecords(TInt aOpCount)
       
   407 	{
       
   408 	for(TInt i=0;i<aOpCount;++i)
       
   409 		{
       
   410 		_LIT8(KDeleteSql, "DELETE FROM A WHERE I=%d\x0");
       
   411 		TBuf8<sizeof(KDeleteSql) + 10> sqlBuf2;
       
   412 		sqlBuf2.Format(KDeleteSql, i + 1);
       
   413 		TInt err = ::DbExecStmt8(TheDbHandle, sqlBuf2);
       
   414 		TEST2(err, KErrNone);
       
   415 		}
       
   416 	}
       
   417 
       
   418 void CSqlCompactTestActive::DeleteTestRecords2()
       
   419 	{
       
   420 	_LIT8(KDeleteSql, "DELETE FROM A\x0");
       
   421 	TInt err = ::DbExecStmt8(TheDbHandle, KDeleteSql);
       
   422 	TEST2(err, KErrNone);
       
   423 	}
       
   424 
       
   425 void CSqlCompactTestActive::TestEnd()
       
   426 	{
       
   427 	TInt freePageCount = ::FreePageCount();
       
   428 	TEST2(freePageCount, 0);
       
   429 	iCompactor->ReleaseEntry(TheDbName);
       
   430 	::CloseDbHandle(TheDbHandle);
       
   431 	TheDbHandle = NULL;
       
   432 	(void)TheFs.Delete(TheDbName);
       
   433 	}
       
   434 
       
   435 /**
       
   436 @SYMTestCaseID			SYSLIB-SQL-UT-4053
       
   437 @SYMTestCaseDesc		Background compaction scheduled by a set of UPDATE operations.
       
   438 						The test uses the server background compaction classes directly.
       
   439 						The test creates a database, inserts records and updates the records.
       
   440 						The update operations free enough disk space to kick-off the background compaction.
       
   441 						The test active object, that simulates the SQL server, is activated and the
       
   442 						background compaction - executed.
       
   443 						The test checks at the end that the background compaction really happened - in
       
   444 						CSqlCompactTestActive::UpdateTestEnd().
       
   445 @SYMTestPriority		Medium
       
   446 @SYMTestActions			Background compaction scheduled by a set of UPDATE operations.
       
   447 @SYMTestExpectedResults Test must not fail
       
   448 @SYMREQ					REQ10271
       
   449                         REQ10272
       
   450 */
       
   451 void CSqlCompactTestActive::UpdateTestBegin()
       
   452 	{
       
   453 	CreateTestDatabase();
       
   454 	TRAPD(err, iCompactor->AddEntryL(TheDbName, TheCompactionSettings));
       
   455 	TEST2(err, KErrNone);
       
   456 	InsertTestRecords();
       
   457 	UpdateTestRecords();
       
   458 	TInt freePageCount = ::FreePageCount();
       
   459 	TEST(freePageCount > KFreePageThreshold);
       
   460 	}
       
   461 
       
   462 void CSqlCompactTestActive::UpdateTestEnd()
       
   463 	{
       
   464 	TestEnd();
       
   465 	}
       
   466 
       
   467 /**
       
   468 @SYMTestCaseID			SYSLIB-SQL-UT-4054
       
   469 @SYMTestCaseDesc		Background compaction scheduled by a set of DELETE operations.
       
   470 						The test uses the server background compaction classes directly.
       
   471 						The test creates a database, inserts records and deletes the records.
       
   472 						The delete operations free enough disk space to kick-off the background compaction.
       
   473 						The test active object, that simulates the SQL server, is activated and the
       
   474 						background compaction - executed.
       
   475 						The test checks at the end that the background compaction really happened - in
       
   476 						CSqlCompactTestActive::DeleteTestEnd().
       
   477 @SYMTestPriority		Medium
       
   478 @SYMTestActions			Background compaction scheduled by a set of DELETE operations.
       
   479 @SYMTestExpectedResults Test must not fail
       
   480 @SYMREQ					REQ10271
       
   481                         REQ10272
       
   482 */
       
   483 void CSqlCompactTestActive::DeleteTestBegin()
       
   484 	{
       
   485 	CreateTestDatabase();
       
   486 	TRAPD(err, iCompactor->AddEntryL(TheDbName, TheCompactionSettings));
       
   487 	TEST2(err, KErrNone);
       
   488 	InsertTestRecords();
       
   489 	DeleteTestRecords();
       
   490 	TInt freePageCount = ::FreePageCount();
       
   491 	TEST(freePageCount >= KFreePageThreshold);
       
   492 	}
       
   493 	
       
   494 void CSqlCompactTestActive::DeleteTestEnd()
       
   495 	{
       
   496 	TestEnd();
       
   497 	}
       
   498 
       
   499 /**
       
   500 @SYMTestCaseID			SYSLIB-SQL-UT-4055
       
   501 @SYMTestCaseDesc		Background compaction, initiated by a single operation.
       
   502 						The test uses the server background compaction classes directly.
       
   503 						The test creates a database, inserts records and deletes the records using just
       
   504 						a single DELETE SQL statement.
       
   505 						The test active object, that simulates the SQL server, schedules 
       
   506 						CSqlCompactTestActive::SingleOpCompactTestEnd() for execution. The code in
       
   507 						SingleOpCompactTestEnd() checks that the background compaction has been activated and closes the
       
   508 						database connection. The "database close" operation should start the compaction
       
   509 						because the total size of free pages is above the "free pages" threshold (in Kb).
       
   510 @SYMTestPriority		Medium
       
   511 @SYMTestActions			Background compaction, initiated by a single operation.
       
   512 @SYMTestExpectedResults Test must not fail
       
   513 @SYMREQ					REQ10271
       
   514                         REQ10272
       
   515 */
       
   516 void CSqlCompactTestActive::SingleOpCompactTestBegin()
       
   517 	{
       
   518 	CreateTestDatabase();
       
   519 	TRAPD(err, iCompactor->AddEntryL(TheDbName, TheCompactionSettings));
       
   520 	TEST2(err, KErrNone);
       
   521 	InsertTestRecords();
       
   522 	DeleteTestRecords2();
       
   523 	TInt freePageCount = ::FreePageCount();
       
   524 	TEST(freePageCount >= KFreePageThreshold);
       
   525 	}
       
   526 
       
   527 void CSqlCompactTestActive::SingleOpCompactTestEnd()
       
   528 	{
       
   529 	TestEnd();
       
   530 	}
       
   531 
       
   532 //Background compaction - OOM test.
       
   533 //CSqlCompactor::NewL() is the function tested in an OOM simulation loop.
       
   534 //The expectation is that if the iteration fails with KErrNoMemory, no memory leak will occur and the compactor object won't be created.
       
   535 void CSqlCompactTestActive::DoOomTest1()
       
   536 	{
       
   537 	TInt err = KErrNoMemory;
       
   538 	TInt failingAllocationNo = 0;
       
   539 	while(err == KErrNoMemory)
       
   540 		{
       
   541 		MarkHandles();
       
   542 		MarkAllocatedCells();
       
   543 				
       
   544 		__UHEAP_MARK;
       
   545 		
       
   546 		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
       
   547 		
       
   548 		CSqlCompactor* compactor = NULL;
       
   549 		TRAP(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
       
   550 		
       
   551 		__UHEAP_RESET;
       
   552 
       
   553 		if(err == KErrNone)	
       
   554 			{
       
   555 			TEST(compactor != NULL);
       
   556 			delete compactor;
       
   557 			}
       
   558 		else
       
   559 			{
       
   560 			TEST(!compactor);
       
   561 			TEST2(err, KErrNoMemory);	
       
   562 			}
       
   563 							
       
   564 		__UHEAP_MARKEND;
       
   565 
       
   566 		CheckAllocatedCells();	    	
       
   567 		CheckHandles();	    	
       
   568 		}
       
   569 	TEST2(err, KErrNone);
       
   570 	TheTest.Printf(_L("=== CSqlCompactor::NewL() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
       
   571 	}
       
   572 
       
   573 //Background compaction - OOM test.
       
   574 //CSqlCompactor::AddEntryL() is the function tested in an OOM simulation loop.
       
   575 //The expectation is that no memory leak will occur if OOM iteration fails with KErrNoMemory.
       
   576 //The expectation also is that if the iteration fails with KErrNoMemory, no entry will be added to the compactor.
       
   577 void CSqlCompactTestActive::DoOomTest2()
       
   578 	{
       
   579 	CSqlCompactor* compactor = NULL;
       
   580 	TRAPD(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
       
   581 	TEST2(err, KErrNone);
       
   582 	TEST(compactor != NULL);
       
   583 	
       
   584 	err = KErrNoMemory;
       
   585 	TInt failingAllocationNo = 0;
       
   586 	while(err == KErrNoMemory)
       
   587 		{
       
   588 		MarkHandles();
       
   589 		MarkAllocatedCells();
       
   590 				
       
   591 		__UHEAP_MARK;
       
   592 		
       
   593 		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
       
   594 		
       
   595 		TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
       
   596 		
       
   597 		__UHEAP_RESET;
       
   598 
       
   599 		if(err == KErrNone)	
       
   600 			{
       
   601 			TEST2(compactor->iEntries.Count(), 1);
       
   602 			compactor->ReleaseEntry(TheDbName);
       
   603 			compactor->iEntries.Compress();
       
   604 			}
       
   605 		else
       
   606 			{
       
   607 			TEST2(compactor->iEntries.Count(), 0);
       
   608 			TEST2(err, KErrNoMemory);	
       
   609 			}
       
   610 							
       
   611 		__UHEAP_MARKEND;
       
   612 
       
   613 		CheckAllocatedCells();	    	
       
   614 		CheckHandles();	    	
       
   615 		}
       
   616 	delete compactor;
       
   617 	TEST2(err, KErrNone);
       
   618 	TheTest.Printf(_L("=== CSqlCompactor::AddEntryL() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
       
   619 	}
       
   620 
       
   621 //Background compaction - OOM test.
       
   622 //CSqlCompactor::NewL() and CSqlCompactor::AddEntryL() are the functions tested in an OOM simulation loop.
       
   623 //At the end of the iteration CSqlCompactor::ReleaseEntry() is not called. 
       
   624 //The CSqlCompactor's destructor should properly release the entry if the compactor and the entry have been created successfully.
       
   625 //The expectation is that no memory leak will occur if OOM iteration fails with KErrNoMemory.
       
   626 void CSqlCompactTestActive::DoOomTest3()
       
   627 	{
       
   628 	TInt err = KErrNoMemory;
       
   629 	TInt failingAllocationNo = 0;
       
   630 	while(err == KErrNoMemory)
       
   631 		{
       
   632 		MarkHandles();
       
   633 		MarkAllocatedCells();
       
   634 				
       
   635 		__UHEAP_MARK;
       
   636 		
       
   637 		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
       
   638 		
       
   639 		CSqlCompactor* compactor = NULL;
       
   640 		TRAP(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
       
   641 		if(err == KErrNone)
       
   642 			{
       
   643 			TRAP(err, (void)compactor->AddEntryL(TheDbName, TheCompactionSettings));
       
   644 			}
       
   645 		
       
   646 		__UHEAP_RESET;
       
   647 
       
   648 		if(err == KErrNone)	
       
   649 			{
       
   650 			TEST(compactor != NULL);
       
   651 			}
       
   652 		else
       
   653 			{
       
   654 			TEST2(err, KErrNoMemory);	
       
   655 			}
       
   656 		delete compactor;
       
   657 							
       
   658 		__UHEAP_MARKEND;
       
   659 
       
   660 		CheckAllocatedCells();	    	
       
   661 		CheckHandles();	    	
       
   662 		}
       
   663 	TEST2(err, KErrNone);
       
   664 	TheTest.Printf(_L("=== CSqlCompactor::NewL()+CSqlCompactor::AddEntryL() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
       
   665 	}
       
   666 
       
   667 //Background compaction - OOM test.
       
   668 //The test database is created inside the OOM loop, at the beginning of each OOM iteration. The database has enough free space.
       
   669 //Then the Compact() method is called. The expectation is that if the iteration fails with KErrNoMemory error, no memory leak will occur.
       
   670 void CSqlCompactTestActive::DoOomTest4()
       
   671 	{
       
   672 	TInt err = KErrNoMemory;
       
   673 	TInt failingAllocationNo = 0;
       
   674 	while(err == KErrNoMemory)
       
   675 		{
       
   676 		MarkHandles();
       
   677 		MarkAllocatedCells();
       
   678 						
       
   679 		__UHEAP_MARK;
       
   680 		
       
   681 		(void)TheFs.Delete(TheDbName);
       
   682 		CreateTestDatabase();
       
   683 		CSqlCompactor* compactor = NULL;
       
   684 		TRAP(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
       
   685 		TEST2(err, KErrNone);
       
   686 		TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
       
   687 		TEST2(err, KErrNone);
       
   688 		InsertTestRecords();
       
   689 		DeleteTestRecords();
       
   690 		TInt freePageCount = ::FreePageCount();
       
   691 		TEST(freePageCount >= KFreePageThreshold);
       
   692 		
       
   693 		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
       
   694 
       
   695 		CSqlCompactEntry* impl = compactor->iEntries[0];
       
   696 		err = impl->Compact();
       
   697 		
       
   698 		__UHEAP_RESET;
       
   699 
       
   700 		if(err != KErrNone)	
       
   701 			{
       
   702 			TEST2(err, KErrNoMemory);	
       
   703 			}
       
   704 		else
       
   705 			{
       
   706 			TInt freePageCount2 = ::FreePageCount();
       
   707 			TEST(freePageCount2 < freePageCount);
       
   708 			}
       
   709 		delete compactor;
       
   710 		::CloseDbHandle(TheDbHandle);
       
   711 		TheDbHandle = NULL;
       
   712 							
       
   713 		__UHEAP_MARKEND;
       
   714 
       
   715 		CheckAllocatedCells();	    	
       
   716 		CheckHandles();	    	
       
   717 		}
       
   718 	TEST2(err, KErrNone);
       
   719 	TheTest.Printf(_L("=== CSqlCompactEntry::Compact() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
       
   720 	(void)TheFs.Delete(TheDbName);
       
   721 	}
       
   722 
       
   723 //Background compaction - OOM test.
       
   724 //The test database is created outside the OOM loop. The database has enough free space.
       
   725 //Then the Compact() method is called under OOM simulation. 
       
   726 //The expectation is that if the iteration fails with KErrNoMemory error, no memory leak will occur and the number of 
       
   727 //the free pages is the same as it was at the beginning of the OOM iteration.
       
   728 void CSqlCompactTestActive::DoOomTest5()
       
   729 	{
       
   730 	__UHEAP_MARK;
       
   731 	
       
   732 	CreateTestDatabase();
       
   733 	CSqlCompactor* compactor = NULL;
       
   734 	TRAPD(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
       
   735 	TEST2(err, KErrNone);
       
   736 	TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
       
   737 	TEST2(err, KErrNone);
       
   738 	InsertTestRecords();
       
   739 	DeleteTestRecords();
       
   740 	TInt freePageCount = ::FreePageCount();
       
   741 	TEST(freePageCount >= KFreePageThreshold);
       
   742 	err = KErrNoMemory;
       
   743 	TInt failingAllocationNo = 0;
       
   744 	while(err == KErrNoMemory)
       
   745 		{
       
   746 		TInt freePageCount2 = ::FreePageCount();
       
   747 		
       
   748 		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
       
   749 
       
   750 		CSqlCompactEntry* impl = compactor->iEntries[0];
       
   751 		impl->iPageCount = freePageCount2;
       
   752 		err = impl->Compact();
       
   753 		
       
   754 		__UHEAP_RESET;
       
   755 
       
   756 		if(err != KErrNone)	
       
   757 			{
       
   758 			TEST2(err, KErrNoMemory);	
       
   759 			TInt freePageCount3 = ::FreePageCount();
       
   760 			TEST2(freePageCount2, freePageCount3);
       
   761 			}
       
   762 	}
       
   763 	TEST2(err, KErrNone);
       
   764 	TInt freePageCount4 = ::FreePageCount();
       
   765 	TEST(freePageCount4 < freePageCount);
       
   766 
       
   767 	compactor->ReleaseEntry(TheDbName);
       
   768 	delete compactor;
       
   769 	::CloseDbHandle(TheDbHandle);
       
   770 	TheDbHandle = NULL;
       
   771 	
       
   772 	__UHEAP_MARKEND;
       
   773 	
       
   774 	TheTest.Printf(_L("=== CSqlCompactEntry::Compact()-2 OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
       
   775 	(void)TheFs.Delete(TheDbName);
       
   776 	}
       
   777 
       
   778 /**
       
   779 @SYMTestCaseID			SYSLIB-SQL-UT-4050
       
   780 @SYMTestCaseDesc		Background compaction - OOM tests.
       
   781 						The test uses directly the SQL server background compaction classes and does OOM tests for:
       
   782 						creating the database compaction object (CSqlCompactor), adding a new background database connection, 
       
   783 						calling directly the background compaction method.
       
   784 @SYMTestPriority		Medium
       
   785 @SYMTestActions			Background compaction - OOM tests.
       
   786 @SYMTestExpectedResults Test must not fail
       
   787 @SYMREQ					REQ10271
       
   788 */
       
   789 void CSqlCompactTestActive::OomTest()
       
   790 	{
       
   791 	CreateTestDatabase();
       
   792 	::CloseDbHandle(TheDbHandle);
       
   793 	TheDbHandle = NULL;
       
   794 	
       
   795 	DoOomTest1();
       
   796 	DoOomTest2();
       
   797 	DoOomTest3();
       
   798 
       
   799 	(void)TheFs.Delete(TheDbName);
       
   800 	
       
   801 	DoOomTest4();
       
   802 	DoOomTest5();
       
   803 	}
       
   804 
       
   805 /**
       
   806 @SYMTestCaseID			SYSLIB-SQL-UT-4051
       
   807 @SYMTestCaseDesc		Background compaction - file I/O error simulation test.
       
   808 						The test calls the background compaction method, CSqlCompactEntry::Compact(),
       
   809 						in a file I/O error simulation loop.
       
   810 @SYMTestPriority		Medium
       
   811 @SYMTestActions			Background compaction - file I/O error simulation test.
       
   812 @SYMTestExpectedResults Test must not fail
       
   813 @SYMREQ					REQ10271
       
   814 */
       
   815 void CSqlCompactTestActive::FileIoErrTest()
       
   816 	{
       
   817 	CreateTestDatabase();
       
   818 	CSqlCompactor* compactor = NULL;
       
   819 	TRAPD(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
       
   820 	TEST2(err, KErrNone);
       
   821 	TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
       
   822 	TEST2(err, KErrNone);
       
   823 	InsertTestRecords();
       
   824 	DeleteTestRecords();
       
   825 	TInt freePageCount = ::FreePageCount();
       
   826 	TEST(freePageCount >= KFreePageThreshold);
       
   827 	err = KErrGeneral;
       
   828 	TInt ioCounter = 0;
       
   829 	while(err != KErrNone)
       
   830 		{
       
   831 		TInt freePageCount2 = ::FreePageCount();
       
   832 		if(freePageCount2 == 0)
       
   833 			{
       
   834 			err = KErrNone;
       
   835 			break;	
       
   836 			}
       
   837 		
       
   838 		(void)TheFs.SetErrorCondition(err, ++ioCounter);
       
   839 
       
   840 		CSqlCompactEntry* impl = compactor->iEntries[0];
       
   841 		impl->iPageCount = freePageCount2;
       
   842 		err = impl->Compact();
       
   843 		
       
   844 		(void)TheFs.SetErrorCondition(KErrNone);
       
   845 
       
   846 		//check the database free pages count - all bets are off in a case of an I/O error. 
       
   847 		//The free page count may actually have been reduced.
       
   848 		TInt freePageCount3 = ::FreePageCount();
       
   849 		TEST(freePageCount3  <= freePageCount2);
       
   850 		}
       
   851 	TEST2(err, KErrNone);
       
   852 	TInt freePageCount4 = ::FreePageCount();
       
   853 
       
   854 	compactor->ReleaseEntry(TheDbName);
       
   855 	delete compactor;
       
   856 	::CloseDbHandle(TheDbHandle);
       
   857 	TheDbHandle = NULL;
       
   858 	
       
   859 	TheTest.Printf(_L("=== CSqlCompactEntry::Compact() \"file I/O\" error simulation test succeeded at iteration %d, free pages %d ===\r\n"), ioCounter, freePageCount4);
       
   860 	(void)TheFs.Delete(TheDbName);
       
   861 	}
       
   862 
       
   863 /**
       
   864 @SYMTestCaseID			SYSLIB-SQL-UT-4052
       
   865 @SYMTestCaseDesc		Compaction - performance test.
       
   866 						The test creates a test database (the default drive is C:, but different drive 
       
   867 						can be specified as a test argument) and runs a compaction performance test. 
       
   868 						The performance result is printed out.
       
   869 @SYMTestPriority		Medium
       
   870 @SYMTestActions			Compaction - performance test.
       
   871 @SYMTestExpectedResults Test must not fail
       
   872 @SYMREQ					REQ10271
       
   873                         REQ10272
       
   874 */
       
   875 void CSqlCompactTestActive::PerformanceTest()
       
   876 	{
       
   877 	TInt err = TheParse.Set(TheDbName, NULL, NULL);
       
   878 	TEST2(err, KErrNone);
       
   879 	TPtrC driveName = TheParse.Drive();
       
   880 	TEST(driveName.Length() > 0);
       
   881 	TInt driveNumber = -1;
       
   882 	err = RFs::CharToDrive(driveName[0], driveNumber);
       
   883 	TEST2(err, KErrNone);
       
   884 	TDriveNumber driveNo = static_cast <TDriveNumber> (driveNumber);
       
   885 	TDriveInfo driveInfo;
       
   886 	err = TheFs.Drive(driveInfo, driveNo);
       
   887 	TEST2(err, KErrNone);
       
   888 	
       
   889 	_LIT(KType1, "Not present");
       
   890 	_LIT(KType2, "Unknown");
       
   891 	_LIT(KType3, "Floppy");
       
   892 	_LIT(KType4, "Hard disk");
       
   893 	_LIT(KType5, "CD ROM");
       
   894 	_LIT(KType6, "RAM disk");
       
   895 	_LIT(KType7, "Flash");
       
   896 	_LIT(KType8, "ROM drive");
       
   897 	_LIT(KType9, "Remote drive");
       
   898 	_LIT(KType10,"NAND flash");
       
   899 	_LIT(KType11,"Rotating media");
       
   900 	TPtrC KMediaTypeNames[] = {KType1(), KType2(), KType3(), KType4(), KType5(), KType6(), KType7(), KType8(), KType9(), KType10(), KType11()};
       
   901 	TheTest.Printf(_L("Drive: %C: %S. File: \"%S\"\r\n"), 'A' + driveNo, &KMediaTypeNames[driveInfo.iType], &TheDbName);
       
   902 
       
   903 	(void)TheFs.Delete(TheDbName);
       
   904 	CreateTestDatabase();
       
   905 	const TInt KRecCount = 90;
       
   906 	InsertTestRecords(KRecCount);
       
   907 	DeleteTestRecords2();
       
   908 	TInt freePageCount = ::FreePageCount();
       
   909 	TInt processedPages = 0;
       
   910 	TheTest.Printf(_L("   Free pages count = %d\r\n"), freePageCount);
       
   911 	TUint32 start = User::FastCounter();
       
   912 	err = ::DbCompact(TheDbHandle, KNullDesC, freePageCount, processedPages);
       
   913 	TUint32 end = User::FastCounter();
       
   914 	TEST2(err, KErrNone);
       
   915 	TEST2(processedPages, freePageCount);
       
   916 	::CloseDbHandle(TheDbHandle);
       
   917 	TheDbHandle = NULL;
       
   918 	(void)TheFs.Delete(TheDbName);
       
   919 	PrintInfo(processedPages, KMediaTypeNames[driveInfo.iType], start, end);
       
   920 	}
       
   921 
       
   922 //////////////////////////////////////////////////////////////////////////////////////////////////
       
   923 
       
   924 void DoTests()
       
   925 	{
       
   926 	CActiveScheduler* scheduler = new CActiveScheduler;
       
   927 	TEST(scheduler != NULL);
       
   928 	CActiveScheduler::Install(scheduler);
       
   929 	
       
   930 	CSqlCompactTestActive::New();
       
   931 	
       
   932 	TheCompactionSettings.iFreePageThresholdKb = KFreePageThresholdKb;
       
   933 
       
   934 	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4050 \"Out of memory\" test"));
       
   935 	TheTestActive->OomTest();
       
   936 	
       
   937 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4051 \"File I/O\" error simulation test"));
       
   938 	TheTestActive->FileIoErrTest();
       
   939 
       
   940 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4052 Compaction - performance test"));
       
   941 	TheTestActive->PerformanceTest();
       
   942 
       
   943 	CActiveScheduler::Start();
       
   944 	
       
   945 	delete TheTestActive;
       
   946 	TheTestActive = NULL;
       
   947 	delete scheduler;
       
   948 	}
       
   949 
       
   950 //////////////////////////////////////////////////////////////////////////////////////////////////
       
   951 
       
   952 //Usage: "t_sqlcompact2 [<drive letter>:]"
       
   953 
       
   954 TInt E32Main()
       
   955 	{
       
   956 	TheTest.Title();
       
   957 	
       
   958 	TheTrapCleanup = CTrapCleanup::New ();
       
   959 	__ASSERT_ALWAYS(TheTrapCleanup != NULL, User::Invariant());
       
   960 
       
   961 	__UHEAP_MARK;
       
   962 
       
   963 	User::CommandLine(TheCmd);
       
   964 	TheCmd.TrimAll();
       
   965 	if(TheCmd.Length() > 0)
       
   966 		{
       
   967 		TheDriveName.Copy(TheCmd);
       
   968 		}
       
   969 
       
   970 	_LIT(KDbName, "c:\\test\\t_sqlcompact2_1.db");
       
   971 	TheParse.Set(TheDriveName, &KDbName, 0);
       
   972 	const TDesC& dbFilePath = TheParse.FullName();
       
   973 	TheDbName.Copy(dbFilePath);
       
   974 	
       
   975 	TestEnvCreate();
       
   976 	
       
   977 	DoTests();
       
   978 
       
   979 	TestEnvDestroy();
       
   980 	
       
   981 	__UHEAP_MARKEND;
       
   982 
       
   983 	TheTest.End();
       
   984 	TheTest.Close();
       
   985 
       
   986 	delete TheTrapCleanup;
       
   987 
       
   988 	return KErrNone;
       
   989 	}