os/persistentdata/persistentstorage/sql/TEST/t_sqlcompact2.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sql/TEST/t_sqlcompact2.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1084 @@
     1.4 +// Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <f32file.h>
    1.20 +#include <e32test.h>
    1.21 +#include <hal.h>
    1.22 +#include <stdlib.h>
    1.23 +#include <sqldb.h>
    1.24 +#include "sqlite3.h"
    1.25 +#include "SqliteSymbian.h"
    1.26 +#include "SqlSrvStatementUtil.h"
    1.27 +#include "SqlPanic.h"
    1.28 +#include "SqlCompact.h"
    1.29 +#include "SqlCompactConn.h"
    1.30 +#include "SqlCompactEntry.h"
    1.31 +#include "SqlUtil.h"
    1.32 +
    1.33 +const TInt KOperationCount = 20;
    1.34 +const TInt KFreePageThresholdKb = 5;
    1.35 +const TInt KFreePageThreshold = 5;
    1.36 +
    1.37 +const TInt KCompactStepInterval = 5;//ms
    1.38 +
    1.39 +TSqlCompactSettings TheCompactionSettings;
    1.40 +
    1.41 +static RTest 			TheTest(_L ("t_sqlcompact2.exe"));
    1.42 +static CTrapCleanup*	TheTrapCleanup = NULL;
    1.43 +static RFs 				TheFs;
    1.44 +static TBuf<KMaxFileName + 1> TheFileNameZ;
    1.45 +static TBuf8<KMaxFileName + 1> TheFileNameZ8;
    1.46 +
    1.47 +const TInt KBlobMaxSize = 1024 * 32;
    1.48 +static TBuf8<KBlobMaxSize> TheBlob;
    1.49 +
    1.50 +static sqlite3* 		TheDbHandle = NULL;
    1.51 +
    1.52 +_LIT8(KFreePageCountPragma, "PRAGMA freelist_count\x0");
    1.53 +
    1.54 +TBuf<256>  TheCmd;
    1.55 +TDriveName TheDriveName;
    1.56 +TParse     TheParse;
    1.57 +TFileName  TheDbName;
    1.58 +
    1.59 +class CSqlCompactTestActive;
    1.60 +CSqlCompactTestActive* TheTestActive = NULL;
    1.61 +
    1.62 +const TTimeIntervalMicroSeconds32 KInterval(200000);
    1.63 +
    1.64 +static TInt TheProcessHandleCount = 0;
    1.65 +static TInt TheThreadHandleCount = 0;
    1.66 +static TInt TheAllocatedCellsCount = 0;
    1.67 +
    1.68 +#ifdef _DEBUG
    1.69 +const TInt KBurstRate = 100;
    1.70 +#endif
    1.71 +
    1.72 +//////////////////////////////////////////////////////////////////////////////////////////////////
    1.73 +
    1.74 +void DeleteTestFiles()
    1.75 +	{
    1.76 +	::CloseDbHandle(TheDbHandle);
    1.77 +	(void)TheFs.Delete(TheDbName);
    1.78 +	}
    1.79 +
    1.80 +///////////////////////////////////////////////////////////////////////////////////////
    1.81 +//Test macros and functions
    1.82 +void Check(TInt aValue, TInt aLine)
    1.83 +	{
    1.84 +	if(!aValue)
    1.85 +		{
    1.86 +		DeleteTestFiles();
    1.87 +		TheTest(EFalse, aLine);
    1.88 +		}
    1.89 +	}
    1.90 +void Check(TInt aValue, TInt aExpected, TInt aLine)
    1.91 +	{
    1.92 +	if(aValue != aExpected)
    1.93 +		{
    1.94 +		DeleteTestFiles();
    1.95 +		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
    1.96 +		TheTest(EFalse, aLine);
    1.97 +		}
    1.98 +	}
    1.99 +#define TEST(arg) ::Check((arg), __LINE__)
   1.100 +#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
   1.101 +
   1.102 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.103 +
   1.104 +void TestEnvCreate()
   1.105 +	{	
   1.106 +	TInt err = sqlite3SymbianLibInit();
   1.107 +	__ASSERT_ALWAYS(err == KErrNone, User::Invariant());
   1.108 +	TheFs = sqlite3SymbianFs();
   1.109 +	for(TInt i=0;i<('Z'-'A');++i)
   1.110 +		{
   1.111 +		TheFs.CreatePrivatePath(i);
   1.112 +		}
   1.113 +	err = TheFs.MkDir(TheDbName);
   1.114 +	TEST(err == KErrNone || err == KErrAlreadyExists);
   1.115 +	DeleteTestFiles();
   1.116 +	}
   1.117 +
   1.118 +void TestEnvDestroy()
   1.119 +	{
   1.120 +	DeleteTestFiles();
   1.121 +	sqlite3SymbianLibFinalize();
   1.122 +	CloseSTDLIB();
   1.123 +	}
   1.124 +
   1.125 +//////////////////////////////////////////////////////////////////////////////////////////////////
   1.126 +
   1.127 +void MarkHandles()
   1.128 +	{
   1.129 +	RThread().HandleCount(TheProcessHandleCount, TheThreadHandleCount);
   1.130 +	}
   1.131 +	
   1.132 +void MarkAllocatedCells()
   1.133 +	{
   1.134 +	TheAllocatedCellsCount = User::CountAllocCells();
   1.135 +	}
   1.136 +
   1.137 +void CheckHandles()
   1.138 +	{
   1.139 +	TInt processHandleCount = 0;
   1.140 +	TInt threadHandleCount = 0;
   1.141 +
   1.142 +	RThread().HandleCount(processHandleCount, threadHandleCount);
   1.143 +
   1.144 +	TEST(processHandleCount == TheProcessHandleCount);
   1.145 +	TEST(threadHandleCount == TheThreadHandleCount);
   1.146 +	}
   1.147 +	
   1.148 +void CheckAllocatedCells()
   1.149 +	{
   1.150 +	TInt allocatedCellsCount = User::CountAllocCells();
   1.151 +	TEST(allocatedCellsCount == TheAllocatedCellsCount);
   1.152 +	}
   1.153 +		
   1.154 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.155 +
   1.156 +const TDesC& FileNameZ(const TDesC& aFileName)
   1.157 +	{
   1.158 +	TheFileNameZ.Copy(aFileName);
   1.159 +	TheFileNameZ.ZeroTerminate();
   1.160 +	return TheFileNameZ;
   1.161 +	}
   1.162 +
   1.163 +const TDesC8& FileNameZ8(const TDesC& aFileName)
   1.164 +	{
   1.165 +	TheFileNameZ8.Copy(aFileName);
   1.166 +	TheFileNameZ8.ZeroTerminate();
   1.167 +	return TheFileNameZ8;
   1.168 +	}
   1.169 +
   1.170 +TInt FreePageCount()
   1.171 +	{
   1.172 +	sqlite3_stmt* stmtHandle = NULL;
   1.173 +	TInt err = ::StmtPrepare8(TheDbHandle, KFreePageCountPragma, stmtHandle);
   1.174 +	TEST2(err, KErrNone);
   1.175 +	TEST(stmtHandle != NULL);
   1.176 +	err = ::StmtNext(stmtHandle);
   1.177 +	TEST2(err, KSqlAtRow);
   1.178 +	TInt pageCount = sqlite3_column_int(stmtHandle, 0);
   1.179 +	TEST(pageCount >= 0);
   1.180 +	::FinalizeStmtHandle(stmtHandle);
   1.181 +	return pageCount;
   1.182 +	}
   1.183 +
   1.184 +void PrintInfo(TInt aProcessedPages, const TDesC& aMediaTypeName, TUint32 aStartTicks, TUint32 aEndTicks)
   1.185 +	{
   1.186 +	static TInt freq = 0;
   1.187 +	if(freq == 0)
   1.188 +		{
   1.189 +		TEST2(HAL::Get(HAL::EFastCounterFrequency, freq), KErrNone);
   1.190 +		}
   1.191 +	TInt64 diffTicks = (TInt64)aEndTicks - (TInt64)aStartTicks;
   1.192 +	if(diffTicks < 0)
   1.193 +		{
   1.194 +		diffTicks = KMaxTUint32 + diffTicks + 1;
   1.195 +		}
   1.196 +	const TInt KMicroSecIn1Sec = 1000000;
   1.197 +	TInt32 us = (diffTicks * KMicroSecIn1Sec) / freq;
   1.198 +	TheTest.Printf(_L("####Media type: %S. Processed pages: %d. Ticks: %ld. Execution time: %d ms\r\n"), 
   1.199 +							&aMediaTypeName, aProcessedPages, diffTicks, us / 1000);
   1.200 +	}
   1.201 +
   1.202 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.203 +//////////////////////////////        CSqlCompactTestActive declaration              /////////////////////////////////////////////
   1.204 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.205 +
   1.206 +class CSqlCompactTestActive : public CActive
   1.207 +	{
   1.208 +private:
   1.209 +	enum TCommand
   1.210 +		{
   1.211 +		ECmdInvalidTest,	
   1.212 +		ECmdBeginTest1,
   1.213 +		ECmdEndTest1,
   1.214 +		ECmdBeginTest2,
   1.215 +		ECmdEndTest2,
   1.216 +		ECmdBeginTest3,
   1.217 +		ECmdEndTest3,
   1.218 +		ECmdStopTests	
   1.219 +		};
   1.220 +	
   1.221 +public:
   1.222 +	static void New();
   1.223 +	virtual ~CSqlCompactTestActive();
   1.224 +	void OomTest();
   1.225 +	void FileIoErrTest();
   1.226 +	void PerformanceTest();
   1.227 +	void FreePageUpdateTest();
   1.228 +	
   1.229 +protected:		
   1.230 +	virtual void DoCancel();
   1.231 +	virtual void RunL();
   1.232 +	virtual TInt RunError(TInt aError);
   1.233 +	
   1.234 +private:
   1.235 +	CSqlCompactTestActive();
   1.236 +	void Complete(TCommand aNextCommand);
   1.237 +	void Schedule(TCommand aNextCommand, TTimeIntervalMicroSeconds32 aInterval);
   1.238 +
   1.239 +	void CreateTestDatabase();
   1.240 +	void CreateTestDatabase2();
   1.241 +	void PrepareDb(TBool aNewDb);
   1.242 +	void InsertTestRecords(TInt aOpCount = KOperationCount);
   1.243 +	void UpdateTestRecords(TInt aOpCount = KOperationCount);
   1.244 +	void DeleteTestRecords(TInt aOpCount = KOperationCount);
   1.245 +	void DeleteTestRecords2();
   1.246 +	void TestEnd();
   1.247 +	
   1.248 +	void UpdateTestBegin();
   1.249 +	void UpdateTestEnd();
   1.250 +	void DeleteTestBegin();
   1.251 +	void DeleteTestEnd();
   1.252 +	void SingleOpCompactTestBegin();
   1.253 +	void SingleOpCompactTestEnd();
   1.254 +	void DoOomTest1();
   1.255 +	void DoOomTest2();
   1.256 +	void DoOomTest3();
   1.257 +	void DoOomTest4();
   1.258 +	void DoOomTest5();
   1.259 +
   1.260 +private:
   1.261 +	TInt			iCommand;
   1.262 +	CSqlCompactor*	iCompactor;
   1.263 +	RTimer			iTimer;
   1.264 +
   1.265 +	};
   1.266 +
   1.267 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.268 +//////////////////////////////        CSqlCompactTestActive implementation             ///////////////////////////////////////////
   1.269 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.270 +
   1.271 +void CSqlCompactTestActive::New()
   1.272 +	{
   1.273 +	TheTestActive = new CSqlCompactTestActive;
   1.274 +	TEST(TheTestActive != NULL);
   1.275 +	}
   1.276 +
   1.277 +CSqlCompactTestActive::~CSqlCompactTestActive()
   1.278 +	{
   1.279 +	Cancel();
   1.280 +	iTimer.Close();
   1.281 +	delete iCompactor;
   1.282 +	}
   1.283 +	
   1.284 +void CSqlCompactTestActive::DoCancel()
   1.285 +	{
   1.286 +	iTimer.Cancel();
   1.287 +	TRequestStatus* stat = &iStatus;
   1.288 +	User::RequestComplete(stat, KErrNone);
   1.289 +	}
   1.290 +	
   1.291 +void CSqlCompactTestActive::RunL()
   1.292 +	{
   1.293 +	switch(iCommand)
   1.294 +		{
   1.295 +		case CSqlCompactTestActive::ECmdBeginTest1:
   1.296 +			TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4053 Update test"));
   1.297 +			UpdateTestBegin();
   1.298 +			Schedule(CSqlCompactTestActive::ECmdEndTest1, KInterval);
   1.299 +			break;
   1.300 +		case CSqlCompactTestActive::ECmdEndTest1:
   1.301 +			UpdateTestEnd();
   1.302 +			Complete(CSqlCompactTestActive::ECmdBeginTest2);
   1.303 +			break;
   1.304 +		case CSqlCompactTestActive::ECmdBeginTest2:
   1.305 +			TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4054 Delete test"));
   1.306 +			DeleteTestBegin();
   1.307 +			Schedule(CSqlCompactTestActive::ECmdEndTest2, KInterval);
   1.308 +			break;
   1.309 +		case CSqlCompactTestActive::ECmdEndTest2:
   1.310 +			DeleteTestEnd();
   1.311 +			Complete(CSqlCompactTestActive::ECmdBeginTest3);
   1.312 +			break;
   1.313 +		case CSqlCompactTestActive::ECmdBeginTest3:
   1.314 +			TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4055 Single operation - compaction test"));
   1.315 +			SingleOpCompactTestBegin();
   1.316 +			Schedule(CSqlCompactTestActive::ECmdEndTest3, KInterval);
   1.317 +			break;
   1.318 +		case CSqlCompactTestActive::ECmdEndTest3:
   1.319 +			SingleOpCompactTestEnd();
   1.320 +			Complete(CSqlCompactTestActive::ECmdStopTests);
   1.321 +			break;
   1.322 +		case CSqlCompactTestActive::ECmdStopTests:
   1.323 +			CActiveScheduler::Stop();
   1.324 +			break;
   1.325 +		case CSqlCompactTestActive::ECmdInvalidTest:
   1.326 +		default:
   1.327 +			TEST(0);
   1.328 +			break;
   1.329 +		}
   1.330 +	}
   1.331 +
   1.332 +TInt CSqlCompactTestActive::RunError(TInt aError)
   1.333 +	{
   1.334 +	TEST2(aError, KErrNone);
   1.335 +	return aError;
   1.336 +	}
   1.337 +
   1.338 +CSqlCompactTestActive::CSqlCompactTestActive() :
   1.339 +	CActive(CActive::EPriorityStandard),
   1.340 +	iCommand(CSqlCompactTestActive::ECmdInvalidTest),
   1.341 +	iCompactor(NULL)
   1.342 +	{
   1.343 +	TInt err = sqlite3_enable_shared_cache(1);
   1.344 +	TEST2(err, SQLITE_OK);
   1.345 +	TRAP(err, iCompactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
   1.346 +	TEST2(err, KErrNone);
   1.347 +	err = iTimer.CreateLocal();
   1.348 +	TEST2(err, KErrNone);
   1.349 +	CActiveScheduler::Add(this);
   1.350 +	Complete(CSqlCompactTestActive::ECmdBeginTest1);
   1.351 +	}
   1.352 +
   1.353 +void CSqlCompactTestActive::Complete(CSqlCompactTestActive::TCommand aNextCommand)
   1.354 +	{
   1.355 +	TEST(!IsActive());
   1.356 +	iCommand = aNextCommand;
   1.357 +	TRequestStatus* stat = &iStatus;
   1.358 +	User::RequestComplete(stat, KErrNone);
   1.359 +	SetActive();	
   1.360 +	}
   1.361 +
   1.362 +void CSqlCompactTestActive::Schedule(TCommand aNextCommand, TTimeIntervalMicroSeconds32 aInterval)
   1.363 +	{
   1.364 +	TEST(!IsActive());
   1.365 +	iCommand = aNextCommand;
   1.366 +	iTimer.After(iStatus, aInterval);
   1.367 +	TEST2(iStatus.Int(), KRequestPending);
   1.368 +	SetActive();
   1.369 +	}
   1.370 +
   1.371 +void CSqlCompactTestActive::CreateTestDatabase()
   1.372 +	{
   1.373 +	TInt err = ::CreateDbHandle8(::FileNameZ8(TheDbName), TheDbHandle);
   1.374 +	TEST2(err, KErrNone);
   1.375 +	_LIT8(KCreateTableSql, "CREATE TABLE A(I INTEGRER, B BLOB)\x0");
   1.376 +	err = ::DbExecStmt8(TheDbHandle, KCreateTableSql);
   1.377 +	TEST2(err, KErrNone);
   1.378 +	}
   1.379 +
   1.380 +void CSqlCompactTestActive::InsertTestRecords(TInt aOpCount)
   1.381 +	{
   1.382 +	TheBlob.SetLength(SQLITE_DEFAULT_PAGE_SIZE);
   1.383 +	for(TInt i=0;i<aOpCount;++i)
   1.384 +		{
   1.385 +		_LIT8(KInsertSql, "INSERT INTO A VALUES(%d, :Prm)\x0");
   1.386 +		TBuf8<sizeof(KInsertSql) + 10> sqlBuf1;
   1.387 +		sqlBuf1.Format(KInsertSql, i + 1);
   1.388 +		sqlite3_stmt* stmtHandle = NULL;
   1.389 +		TInt err = ::StmtPrepare8(TheDbHandle, sqlBuf1, stmtHandle);
   1.390 +		TEST2(err, KErrNone);
   1.391 +		TEST(stmtHandle != NULL);
   1.392 +		err = sqlite3_bind_blob(stmtHandle, 1, TheBlob.Ptr(), SQLITE_DEFAULT_PAGE_SIZE, SQLITE_STATIC);
   1.393 +		TEST2(err, SQLITE_OK);
   1.394 +		err = ::StmtExec(stmtHandle);
   1.395 +		TEST2(err, KErrNone);
   1.396 +		::FinalizeStmtHandle(stmtHandle);
   1.397 +		}
   1.398 +	}
   1.399 +
   1.400 +//Creates a test database (with KDbName name). 
   1.401 +void CSqlCompactTestActive::CreateTestDatabase2()
   1.402 +    {
   1.403 +    //Create the database
   1.404 +    const TInt KPageSize = 1024;
   1.405 +    _LIT8(KConfigStr, "page_size=");
   1.406 +    TBuf8<100> config;
   1.407 +    config.Copy(KConfigStr);
   1.408 +    config.AppendNum(KPageSize);
   1.409 +    TInt err = KErrNone;
   1.410 +    err = ::CreateDbHandle8(::FileNameZ8(TheDbName), TheDbHandle);
   1.411 +    TEST2(err, KErrNone);  
   1.412 +    _LIT8(KCreateTableSql, "CREATE TABLE A(I INTEGER, T TEXT)\x0");
   1.413 +    err = ::DbExecStmt8(TheDbHandle, KCreateTableSql);
   1.414 +    TEST2(err, KErrNone);
   1.415 +    }
   1.416 +
   1.417 +//Insert 1000 records. The record size is such that there is only two records per page.
   1.418 +void CSqlCompactTestActive::PrepareDb(TBool aDeleteRecords)
   1.419 +    {
   1.420 +    //Insert records
   1.421 +    const TInt KRecordCount = 1000;
   1.422 +    const TInt KTextLen = 400;
   1.423 +    TBuf<KTextLen> TheText;
   1.424 +    TBuf<KTextLen + 100> TheSqlBuf;
   1.425 +    TheText.SetLength(TheText.MaxLength());
   1.426 +    TheText.Fill(TChar('A'));
   1.427 +    for(TInt i=0;i<KRecordCount;++i)
   1.428 +        {
   1.429 +        TheSqlBuf.Format(_L("INSERT INTO A VALUES(%d, '%S')"), i + 1, &TheText);
   1.430 +        _LIT(KZero, "\x0");
   1.431 +        TheSqlBuf.Append(KZero);
   1.432 +        TInt err = ::DbExecStmt16(TheDbHandle, TheSqlBuf);
   1.433 +        TEST2(err, KErrNone);
   1.434 +        }
   1.435 +    if(aDeleteRecords)
   1.436 +        {   
   1.437 +        //Delete all records to make a lot of free pages. 
   1.438 +        _LIT(KDeleteAll, "DELETE FROM A WHERE 1\x0");
   1.439 +        TheSqlBuf = KDeleteAll;
   1.440 +        TInt err = ::DbExecStmt16(TheDbHandle, TheSqlBuf);
   1.441 +        TEST2(err, KErrNone);
   1.442 +        }
   1.443 +    }
   1.444 +
   1.445 +void CSqlCompactTestActive::UpdateTestRecords(TInt aOpCount)
   1.446 +	{
   1.447 +	for(TInt i=0;i<aOpCount;++i)
   1.448 +		{
   1.449 +		_LIT8(KUpdateSql, "UPDATE A SET B=x'1122' WHERE I=%d\x0");
   1.450 +		TBuf8<sizeof(KUpdateSql) + 10> sqlBuf2;
   1.451 +		sqlBuf2.Format(KUpdateSql, i + 1);
   1.452 +		TInt err = ::DbExecStmt8(TheDbHandle, sqlBuf2);
   1.453 +		TEST2(err, KErrNone);
   1.454 +		}
   1.455 +	}
   1.456 +
   1.457 +void CSqlCompactTestActive::DeleteTestRecords(TInt aOpCount)
   1.458 +	{
   1.459 +	for(TInt i=0;i<aOpCount;++i)
   1.460 +		{
   1.461 +		_LIT8(KDeleteSql, "DELETE FROM A WHERE I=%d\x0");
   1.462 +		TBuf8<sizeof(KDeleteSql) + 10> sqlBuf2;
   1.463 +		sqlBuf2.Format(KDeleteSql, i + 1);
   1.464 +		TInt err = ::DbExecStmt8(TheDbHandle, sqlBuf2);
   1.465 +		TEST2(err, KErrNone);
   1.466 +		}
   1.467 +	}
   1.468 +
   1.469 +void CSqlCompactTestActive::DeleteTestRecords2()
   1.470 +	{
   1.471 +	_LIT8(KDeleteSql, "DELETE FROM A\x0");
   1.472 +	TInt err = ::DbExecStmt8(TheDbHandle, KDeleteSql);
   1.473 +	TEST2(err, KErrNone);
   1.474 +	}
   1.475 +
   1.476 +void CSqlCompactTestActive::TestEnd()
   1.477 +	{
   1.478 +	TInt freePageCount = ::FreePageCount();
   1.479 +	TEST2(freePageCount, 0);
   1.480 +	iCompactor->ReleaseEntry(TheDbName);
   1.481 +	::CloseDbHandle(TheDbHandle);
   1.482 +	TheDbHandle = NULL;
   1.483 +	(void)TheFs.Delete(TheDbName);
   1.484 +	}
   1.485 +
   1.486 +/**
   1.487 +@SYMTestCaseID			SYSLIB-SQL-UT-4053
   1.488 +@SYMTestCaseDesc		Background compaction scheduled by a set of UPDATE operations.
   1.489 +						The test uses the server background compaction classes directly.
   1.490 +						The test creates a database, inserts records and updates the records.
   1.491 +						The update operations free enough disk space to kick-off the background compaction.
   1.492 +						The test active object, that simulates the SQL server, is activated and the
   1.493 +						background compaction - executed.
   1.494 +						The test checks at the end that the background compaction really happened - in
   1.495 +						CSqlCompactTestActive::UpdateTestEnd().
   1.496 +@SYMTestPriority		Medium
   1.497 +@SYMTestActions			Background compaction scheduled by a set of UPDATE operations.
   1.498 +@SYMTestExpectedResults Test must not fail
   1.499 +@SYMREQ					REQ10271
   1.500 +                        REQ10272
   1.501 +*/
   1.502 +void CSqlCompactTestActive::UpdateTestBegin()
   1.503 +	{
   1.504 +	CreateTestDatabase();
   1.505 +	TRAPD(err, iCompactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.506 +	TEST2(err, KErrNone);
   1.507 +	InsertTestRecords();
   1.508 +	UpdateTestRecords();
   1.509 +	TInt freePageCount = ::FreePageCount();
   1.510 +	TEST(freePageCount > KFreePageThreshold);
   1.511 +	}
   1.512 +
   1.513 +void CSqlCompactTestActive::UpdateTestEnd()
   1.514 +	{
   1.515 +	TestEnd();
   1.516 +	}
   1.517 +
   1.518 +/**
   1.519 +@SYMTestCaseID			SYSLIB-SQL-UT-4054
   1.520 +@SYMTestCaseDesc		Background compaction scheduled by a set of DELETE operations.
   1.521 +						The test uses the server background compaction classes directly.
   1.522 +						The test creates a database, inserts records and deletes the records.
   1.523 +						The delete operations free enough disk space to kick-off the background compaction.
   1.524 +						The test active object, that simulates the SQL server, is activated and the
   1.525 +						background compaction - executed.
   1.526 +						The test checks at the end that the background compaction really happened - in
   1.527 +						CSqlCompactTestActive::DeleteTestEnd().
   1.528 +@SYMTestPriority		Medium
   1.529 +@SYMTestActions			Background compaction scheduled by a set of DELETE operations.
   1.530 +@SYMTestExpectedResults Test must not fail
   1.531 +@SYMREQ					REQ10271
   1.532 +                        REQ10272
   1.533 +*/
   1.534 +void CSqlCompactTestActive::DeleteTestBegin()
   1.535 +	{
   1.536 +	CreateTestDatabase();
   1.537 +	TRAPD(err, iCompactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.538 +	TEST2(err, KErrNone);
   1.539 +	InsertTestRecords();
   1.540 +	DeleteTestRecords();
   1.541 +	TInt freePageCount = ::FreePageCount();
   1.542 +	TEST(freePageCount >= KFreePageThreshold);
   1.543 +	}
   1.544 +	
   1.545 +void CSqlCompactTestActive::DeleteTestEnd()
   1.546 +	{
   1.547 +	TestEnd();
   1.548 +	}
   1.549 +
   1.550 +/**
   1.551 +@SYMTestCaseID			SYSLIB-SQL-UT-4055
   1.552 +@SYMTestCaseDesc		Background compaction, initiated by a single operation.
   1.553 +						The test uses the server background compaction classes directly.
   1.554 +						The test creates a database, inserts records and deletes the records using just
   1.555 +						a single DELETE SQL statement.
   1.556 +						The test active object, that simulates the SQL server, schedules 
   1.557 +						CSqlCompactTestActive::SingleOpCompactTestEnd() for execution. The code in
   1.558 +						SingleOpCompactTestEnd() checks that the background compaction has been activated and closes the
   1.559 +						database connection. The "database close" operation should start the compaction
   1.560 +						because the total size of free pages is above the "free pages" threshold (in Kb).
   1.561 +@SYMTestPriority		Medium
   1.562 +@SYMTestActions			Background compaction, initiated by a single operation.
   1.563 +@SYMTestExpectedResults Test must not fail
   1.564 +@SYMREQ					REQ10271
   1.565 +                        REQ10272
   1.566 +*/
   1.567 +void CSqlCompactTestActive::SingleOpCompactTestBegin()
   1.568 +	{
   1.569 +	CreateTestDatabase();
   1.570 +	TRAPD(err, iCompactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.571 +	TEST2(err, KErrNone);
   1.572 +	InsertTestRecords();
   1.573 +	DeleteTestRecords2();
   1.574 +	TInt freePageCount = ::FreePageCount();
   1.575 +	TEST(freePageCount >= KFreePageThreshold);
   1.576 +	}
   1.577 +
   1.578 +void CSqlCompactTestActive::SingleOpCompactTestEnd()
   1.579 +	{
   1.580 +	TestEnd();
   1.581 +	}
   1.582 +
   1.583 +//Background compaction - OOM test.
   1.584 +//CSqlCompactor::NewL() is the function tested in an OOM simulation loop.
   1.585 +//The expectation is that if the iteration fails with KErrNoMemory, no memory leak will occur and the compactor object won't be created.
   1.586 +void CSqlCompactTestActive::DoOomTest1()
   1.587 +	{
   1.588 +	TInt err = KErrNoMemory;
   1.589 +	TInt failingAllocationNo = 0;
   1.590 +	while(err == KErrNoMemory)
   1.591 +		{
   1.592 +		MarkHandles();
   1.593 +		MarkAllocatedCells();
   1.594 +				
   1.595 +		__UHEAP_MARK;
   1.596 +		
   1.597 +		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
   1.598 +		
   1.599 +		CSqlCompactor* compactor = NULL;
   1.600 +		TRAP(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
   1.601 +		
   1.602 +		__UHEAP_RESET;
   1.603 +
   1.604 +		if(err == KErrNone)	
   1.605 +			{
   1.606 +			TEST(compactor != NULL);
   1.607 +			delete compactor;
   1.608 +			}
   1.609 +		else
   1.610 +			{
   1.611 +			TEST(!compactor);
   1.612 +			TEST2(err, KErrNoMemory);	
   1.613 +			}
   1.614 +							
   1.615 +		__UHEAP_MARKEND;
   1.616 +
   1.617 +		CheckAllocatedCells();	    	
   1.618 +		CheckHandles();	    	
   1.619 +		}
   1.620 +	TEST2(err, KErrNone);
   1.621 +	TheTest.Printf(_L("=== CSqlCompactor::NewL() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
   1.622 +	}
   1.623 +
   1.624 +//Background compaction - OOM test.
   1.625 +//CSqlCompactor::AddEntryL() is the function tested in an OOM simulation loop.
   1.626 +//The expectation is that no memory leak will occur if OOM iteration fails with KErrNoMemory.
   1.627 +//The expectation also is that if the iteration fails with KErrNoMemory, no entry will be added to the compactor.
   1.628 +void CSqlCompactTestActive::DoOomTest2()
   1.629 +	{
   1.630 +	CSqlCompactor* compactor = NULL;
   1.631 +	TRAPD(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
   1.632 +	TEST2(err, KErrNone);
   1.633 +	TEST(compactor != NULL);
   1.634 +	
   1.635 +	err = KErrNoMemory;
   1.636 +	TInt failingAllocationNo = 0;
   1.637 +	while(err == KErrNoMemory)
   1.638 +		{
   1.639 +		MarkHandles();
   1.640 +		MarkAllocatedCells();
   1.641 +				
   1.642 +		__UHEAP_MARK;
   1.643 +		
   1.644 +		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
   1.645 +		
   1.646 +		TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.647 +		
   1.648 +		__UHEAP_RESET;
   1.649 +
   1.650 +		if(err == KErrNone)	
   1.651 +			{
   1.652 +			TEST2(compactor->iEntries.Count(), 1);
   1.653 +			compactor->ReleaseEntry(TheDbName);
   1.654 +			compactor->iEntries.Compress();
   1.655 +			}
   1.656 +		else
   1.657 +			{
   1.658 +			TEST2(compactor->iEntries.Count(), 0);
   1.659 +			TEST2(err, KErrNoMemory);	
   1.660 +			}
   1.661 +							
   1.662 +		__UHEAP_MARKEND;
   1.663 +
   1.664 +		CheckAllocatedCells();	    	
   1.665 +		CheckHandles();	    	
   1.666 +		}
   1.667 +	delete compactor;
   1.668 +	TEST2(err, KErrNone);
   1.669 +	TheTest.Printf(_L("=== CSqlCompactor::AddEntryL() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
   1.670 +	}
   1.671 +
   1.672 +//Background compaction - OOM test.
   1.673 +//CSqlCompactor::NewL() and CSqlCompactor::AddEntryL() are the functions tested in an OOM simulation loop.
   1.674 +//At the end of the iteration CSqlCompactor::ReleaseEntry() is not called. 
   1.675 +//The CSqlCompactor's destructor should properly release the entry if the compactor and the entry have been created successfully.
   1.676 +//The expectation is that no memory leak will occur if OOM iteration fails with KErrNoMemory.
   1.677 +void CSqlCompactTestActive::DoOomTest3()
   1.678 +	{
   1.679 +	TInt err = KErrNoMemory;
   1.680 +	TInt failingAllocationNo = 0;
   1.681 +	while(err == KErrNoMemory)
   1.682 +		{
   1.683 +		MarkHandles();
   1.684 +		MarkAllocatedCells();
   1.685 +				
   1.686 +		__UHEAP_MARK;
   1.687 +		
   1.688 +		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
   1.689 +		
   1.690 +		CSqlCompactor* compactor = NULL;
   1.691 +		TRAP(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
   1.692 +		if(err == KErrNone)
   1.693 +			{
   1.694 +			TRAP(err, (void)compactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.695 +			}
   1.696 +		
   1.697 +		__UHEAP_RESET;
   1.698 +
   1.699 +		if(err == KErrNone)	
   1.700 +			{
   1.701 +			TEST(compactor != NULL);
   1.702 +			}
   1.703 +		else
   1.704 +			{
   1.705 +			TEST2(err, KErrNoMemory);	
   1.706 +			}
   1.707 +		delete compactor;
   1.708 +							
   1.709 +		__UHEAP_MARKEND;
   1.710 +
   1.711 +		CheckAllocatedCells();	    	
   1.712 +		CheckHandles();	    	
   1.713 +		}
   1.714 +	TEST2(err, KErrNone);
   1.715 +	TheTest.Printf(_L("=== CSqlCompactor::NewL()+CSqlCompactor::AddEntryL() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
   1.716 +	}
   1.717 +
   1.718 +//Background compaction - OOM test.
   1.719 +//The test database is created inside the OOM loop, at the beginning of each OOM iteration. The database has enough free space.
   1.720 +//Then the Compact() method is called. The expectation is that if the iteration fails with KErrNoMemory error, no memory leak will occur.
   1.721 +void CSqlCompactTestActive::DoOomTest4()
   1.722 +	{
   1.723 +	TInt err = KErrNoMemory;
   1.724 +	TInt failingAllocationNo = 0;
   1.725 +	while(err == KErrNoMemory)
   1.726 +		{
   1.727 +		MarkHandles();
   1.728 +		MarkAllocatedCells();
   1.729 +						
   1.730 +		__UHEAP_MARK;
   1.731 +		
   1.732 +		(void)TheFs.Delete(TheDbName);
   1.733 +		CreateTestDatabase();
   1.734 +		CSqlCompactor* compactor = NULL;
   1.735 +		TRAP(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
   1.736 +		TEST2(err, KErrNone);
   1.737 +		TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.738 +		TEST2(err, KErrNone);
   1.739 +		InsertTestRecords();
   1.740 +		DeleteTestRecords();
   1.741 +		TInt freePageCount = ::FreePageCount();
   1.742 +		TEST(freePageCount >= KFreePageThreshold);
   1.743 +		
   1.744 +		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
   1.745 +
   1.746 +		CSqlCompactEntry* impl = compactor->iEntries[0];
   1.747 +		err = impl->Compact();
   1.748 +		
   1.749 +		__UHEAP_RESET;
   1.750 +
   1.751 +		if(err != KErrNone)	
   1.752 +			{
   1.753 +			TEST2(err, KErrNoMemory);	
   1.754 +			}
   1.755 +		else
   1.756 +			{
   1.757 +			TInt freePageCount2 = ::FreePageCount();
   1.758 +			TEST(freePageCount2 < freePageCount);
   1.759 +			}
   1.760 +		delete compactor;
   1.761 +		::CloseDbHandle(TheDbHandle);
   1.762 +		TheDbHandle = NULL;
   1.763 +							
   1.764 +		__UHEAP_MARKEND;
   1.765 +
   1.766 +		CheckAllocatedCells();	    	
   1.767 +		CheckHandles();	    	
   1.768 +		}
   1.769 +	TEST2(err, KErrNone);
   1.770 +	TheTest.Printf(_L("=== CSqlCompactEntry::Compact() OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
   1.771 +	(void)TheFs.Delete(TheDbName);
   1.772 +	}
   1.773 +
   1.774 +//Background compaction - OOM test.
   1.775 +//The test database is created outside the OOM loop. The database has enough free space.
   1.776 +//Then the Compact() method is called under OOM simulation. 
   1.777 +//The expectation is that if the iteration fails with KErrNoMemory error, no memory leak will occur and the number of 
   1.778 +//the free pages is the same as it was at the beginning of the OOM iteration.
   1.779 +void CSqlCompactTestActive::DoOomTest5()
   1.780 +	{
   1.781 +	__UHEAP_MARK;
   1.782 +	
   1.783 +	CreateTestDatabase();
   1.784 +	CSqlCompactor* compactor = NULL;
   1.785 +	TRAPD(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
   1.786 +	TEST2(err, KErrNone);
   1.787 +	TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.788 +	TEST2(err, KErrNone);
   1.789 +	InsertTestRecords();
   1.790 +	DeleteTestRecords();
   1.791 +	TInt freePageCount = ::FreePageCount();
   1.792 +	TEST(freePageCount >= KFreePageThreshold);
   1.793 +	err = KErrNoMemory;
   1.794 +	TInt failingAllocationNo = 0;
   1.795 +	while(err == KErrNoMemory)
   1.796 +		{
   1.797 +		TInt freePageCount2 = ::FreePageCount();
   1.798 +		
   1.799 +		__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, ++failingAllocationNo, KBurstRate);
   1.800 +
   1.801 +		CSqlCompactEntry* impl = compactor->iEntries[0];
   1.802 +		impl->iPageCount = freePageCount2;
   1.803 +		err = impl->Compact();
   1.804 +		
   1.805 +		__UHEAP_RESET;
   1.806 +
   1.807 +		if(err != KErrNone)	
   1.808 +			{
   1.809 +			TEST2(err, KErrNoMemory);	
   1.810 +			TInt freePageCount3 = ::FreePageCount();
   1.811 +			TEST2(freePageCount2, freePageCount3);
   1.812 +			}
   1.813 +	}
   1.814 +	TEST2(err, KErrNone);
   1.815 +	TInt freePageCount4 = ::FreePageCount();
   1.816 +	TEST(freePageCount4 < freePageCount);
   1.817 +
   1.818 +	compactor->ReleaseEntry(TheDbName);
   1.819 +	delete compactor;
   1.820 +	::CloseDbHandle(TheDbHandle);
   1.821 +	TheDbHandle = NULL;
   1.822 +	
   1.823 +	__UHEAP_MARKEND;
   1.824 +	
   1.825 +	TheTest.Printf(_L("=== CSqlCompactEntry::Compact()-2 OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
   1.826 +	(void)TheFs.Delete(TheDbName);
   1.827 +	}
   1.828 +
   1.829 +/**
   1.830 +@SYMTestCaseID			SYSLIB-SQL-UT-4050
   1.831 +@SYMTestCaseDesc		Background compaction - OOM tests.
   1.832 +						The test uses directly the SQL server background compaction classes and does OOM tests for:
   1.833 +						creating the database compaction object (CSqlCompactor), adding a new background database connection, 
   1.834 +						calling directly the background compaction method.
   1.835 +@SYMTestPriority		Medium
   1.836 +@SYMTestActions			Background compaction - OOM tests.
   1.837 +@SYMTestExpectedResults Test must not fail
   1.838 +@SYMREQ					REQ10271
   1.839 +*/
   1.840 +void CSqlCompactTestActive::OomTest()
   1.841 +	{
   1.842 +	CreateTestDatabase();
   1.843 +	::CloseDbHandle(TheDbHandle);
   1.844 +	TheDbHandle = NULL;
   1.845 +	
   1.846 +	DoOomTest1();
   1.847 +	DoOomTest2();
   1.848 +	DoOomTest3();
   1.849 +
   1.850 +	(void)TheFs.Delete(TheDbName);
   1.851 +	
   1.852 +	DoOomTest4();
   1.853 +	DoOomTest5();
   1.854 +	}
   1.855 +
   1.856 +/**
   1.857 +@SYMTestCaseID			SYSLIB-SQL-UT-4051
   1.858 +@SYMTestCaseDesc		Background compaction - file I/O error simulation test.
   1.859 +						The test calls the background compaction method, CSqlCompactEntry::Compact(),
   1.860 +						in a file I/O error simulation loop.
   1.861 +@SYMTestPriority		Medium
   1.862 +@SYMTestActions			Background compaction - file I/O error simulation test.
   1.863 +@SYMTestExpectedResults Test must not fail
   1.864 +@SYMREQ					REQ10271
   1.865 +*/
   1.866 +void CSqlCompactTestActive::FileIoErrTest()
   1.867 +	{
   1.868 +	CreateTestDatabase();
   1.869 +	CSqlCompactor* compactor = NULL;
   1.870 +	TRAPD(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
   1.871 +	TEST2(err, KErrNone);
   1.872 +	TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.873 +	TEST2(err, KErrNone);
   1.874 +	InsertTestRecords();
   1.875 +	DeleteTestRecords();
   1.876 +	TInt freePageCount = ::FreePageCount();
   1.877 +	TEST(freePageCount >= KFreePageThreshold);
   1.878 +	err = KErrGeneral;
   1.879 +	TInt ioCounter = 0;
   1.880 +	while(err != KErrNone)
   1.881 +		{
   1.882 +		TInt freePageCount2 = ::FreePageCount();
   1.883 +		if(freePageCount2 == 0)
   1.884 +			{
   1.885 +			err = KErrNone;
   1.886 +			break;	
   1.887 +			}
   1.888 +		
   1.889 +		(void)TheFs.SetErrorCondition(err, ioCounter++);
   1.890 +
   1.891 +		CSqlCompactEntry* impl = compactor->iEntries[0];
   1.892 +		impl->iPageCount = freePageCount2;
   1.893 +		err = impl->Compact();
   1.894 +		
   1.895 +		(void)TheFs.SetErrorCondition(KErrNone);
   1.896 +
   1.897 +		//check the database free pages count - all bets are off in a case of an I/O error. 
   1.898 +		//The free page count may actually have been reduced.
   1.899 +		TInt freePageCount3 = ::FreePageCount();
   1.900 +		TEST(freePageCount3  <= freePageCount2);
   1.901 +		}
   1.902 +	TEST2(err, KErrNone);
   1.903 +	TInt freePageCount4 = ::FreePageCount();
   1.904 +
   1.905 +	compactor->ReleaseEntry(TheDbName);
   1.906 +	delete compactor;
   1.907 +	::CloseDbHandle(TheDbHandle);
   1.908 +	TheDbHandle = NULL;
   1.909 +	
   1.910 +	TheTest.Printf(_L("=== CSqlCompactEntry::Compact() \"file I/O\" error simulation test succeeded at iteration %d, free pages %d ===\r\n"), ioCounter, freePageCount4);
   1.911 +	(void)TheFs.Delete(TheDbName);
   1.912 +	}
   1.913 +
   1.914 +/**
   1.915 +@SYMTestCaseID			SYSLIB-SQL-UT-4052
   1.916 +@SYMTestCaseDesc		Compaction - performance test.
   1.917 +						The test creates a test database (the default drive is C:, but different drive 
   1.918 +						can be specified as a test argument) and runs a compaction performance test. 
   1.919 +						The performance result is printed out.
   1.920 +@SYMTestPriority		Medium
   1.921 +@SYMTestActions			Compaction - performance test.
   1.922 +@SYMTestExpectedResults Test must not fail
   1.923 +@SYMREQ					REQ10271
   1.924 +                        REQ10272
   1.925 +*/
   1.926 +void CSqlCompactTestActive::PerformanceTest()
   1.927 +	{
   1.928 +	TInt err = TheParse.Set(TheDbName, NULL, NULL);
   1.929 +	TEST2(err, KErrNone);
   1.930 +	TPtrC driveName = TheParse.Drive();
   1.931 +	TEST(driveName.Length() > 0);
   1.932 +	TInt driveNumber = -1;
   1.933 +	err = RFs::CharToDrive(driveName[0], driveNumber);
   1.934 +	TEST2(err, KErrNone);
   1.935 +	TDriveNumber driveNo = static_cast <TDriveNumber> (driveNumber);
   1.936 +	TDriveInfo driveInfo;
   1.937 +	err = TheFs.Drive(driveInfo, driveNo);
   1.938 +	TEST2(err, KErrNone);
   1.939 +	
   1.940 +	_LIT(KType1, "Not present");
   1.941 +	_LIT(KType2, "Unknown");
   1.942 +	_LIT(KType3, "Floppy");
   1.943 +	_LIT(KType4, "Hard disk");
   1.944 +	_LIT(KType5, "CD ROM");
   1.945 +	_LIT(KType6, "RAM disk");
   1.946 +	_LIT(KType7, "Flash");
   1.947 +	_LIT(KType8, "ROM drive");
   1.948 +	_LIT(KType9, "Remote drive");
   1.949 +	_LIT(KType10,"NAND flash");
   1.950 +	_LIT(KType11,"Rotating media");
   1.951 +	TPtrC KMediaTypeNames[] = {KType1(), KType2(), KType3(), KType4(), KType5(), KType6(), KType7(), KType8(), KType9(), KType10(), KType11()};
   1.952 +	TheTest.Printf(_L("Drive: %C: %S. File: \"%S\"\r\n"), 'A' + driveNo, &KMediaTypeNames[driveInfo.iType], &TheDbName);
   1.953 +
   1.954 +	(void)TheFs.Delete(TheDbName);
   1.955 +	CreateTestDatabase();
   1.956 +	const TInt KRecCount = 90;
   1.957 +	InsertTestRecords(KRecCount);
   1.958 +	DeleteTestRecords2();
   1.959 +	TInt freePageCount = ::FreePageCount();
   1.960 +	TInt processedPages = 0;
   1.961 +	TheTest.Printf(_L("   Free pages count = %d\r\n"), freePageCount);
   1.962 +	TUint32 start = User::FastCounter();
   1.963 +	err = ::DbCompact(TheDbHandle, KNullDesC, freePageCount, processedPages);
   1.964 +	TUint32 end = User::FastCounter();
   1.965 +	TEST2(err, KErrNone);
   1.966 +	TEST2(processedPages, freePageCount);
   1.967 +	::CloseDbHandle(TheDbHandle);
   1.968 +	TheDbHandle = NULL;
   1.969 +	(void)TheFs.Delete(TheDbName);
   1.970 +	PrintInfo(processedPages, KMediaTypeNames[driveInfo.iType], start, end);
   1.971 +	}
   1.972 +
   1.973 +/**
   1.974 +@SYMTestCaseID          PDS-SQL-CT-4239
   1.975 +@SYMTestCaseDesc        Free page update test.
   1.976 +                        The test creates a database with some records and deletes them all. The records are inserted such that when
   1.977 +                        they get deleted, it leaves a great deal of free pages.
   1.978 +                        Then the test refill the pages which ware empty. After that, the test call ::DbCompact(...) with the number of free
   1.979 +                        pages previously. The free page count should be updated with "0" since all free pages have been refilled since. 
   1.980 +@SYMTestPriority        Medium
   1.981 +@SYMTestExpectedResults Test must not fail
   1.982 +*/
   1.983 +void CSqlCompactTestActive::FreePageUpdateTest()
   1.984 +    {
   1.985 +     (void)TheFs.Delete(TheDbName);
   1.986 +    
   1.987 +    //Create the database with 1000 records and then delete all of them
   1.988 +    CreateTestDatabase2();
   1.989 +    
   1.990 +    CSqlCompactor* compactor = NULL;
   1.991 +    TRAPD(err, compactor = CSqlCompactor::NewL(&SqlCreateCompactConnL, KCompactStepInterval));
   1.992 +    TEST2(err, KErrNone);
   1.993 +    TRAP(err, compactor->AddEntryL(TheDbName, TheCompactionSettings));
   1.994 +    TEST2(err, KErrNone);
   1.995 +
   1.996 +    PrepareDb(ETrue);
   1.997 +    TInt freePageCount = ::FreePageCount();
   1.998 +    TEST(freePageCount > KSqlCompactFreePageThresholdKb);
   1.999 +    TheTest.Printf(_L("   Free pages count = %d\r\n"), freePageCount);
  1.1000 +  
  1.1001 +    //Refill the database
  1.1002 +    PrepareDb(EFalse);
  1.1003 +   
  1.1004 +    CSqlCompactEntry* impl = compactor->iEntries[0];
  1.1005 +    impl->iPageCount = freePageCount;
  1.1006 +    err = impl->Compact();
  1.1007 +    TEST2(err, KErrNone);
  1.1008 +    TEST2(impl->iPageCount, 0);
  1.1009 +
  1.1010 +    compactor->ReleaseEntry(TheDbName);
  1.1011 +    delete compactor;
  1.1012 +    ::CloseDbHandle(TheDbHandle);
  1.1013 +    TheDbHandle = NULL;
  1.1014 +    (void)TheFs.Delete(TheDbName);
  1.1015 +    }
  1.1016 +
  1.1017 +//////////////////////////////////////////////////////////////////////////////////////////////////
  1.1018 +
  1.1019 +void DoTests()
  1.1020 +	{
  1.1021 +	CActiveScheduler* scheduler = new CActiveScheduler;
  1.1022 +	TEST(scheduler != NULL);
  1.1023 +	CActiveScheduler::Install(scheduler);
  1.1024 +	
  1.1025 +	CSqlCompactTestActive::New();
  1.1026 +	
  1.1027 +	TheCompactionSettings.iFreePageThresholdKb = KFreePageThresholdKb;
  1.1028 +
  1.1029 +	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4050 \"Out of memory\" test"));
  1.1030 +	TheTestActive->OomTest();
  1.1031 +	
  1.1032 +	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4051 \"File I/O\" error simulation test"));
  1.1033 +	TheTestActive->FileIoErrTest();
  1.1034 +
  1.1035 +	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4052 Compaction - performance test"));
  1.1036 +	TheTestActive->PerformanceTest();
  1.1037 +	
  1.1038 +	TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4239 Free page update test"));
  1.1039 +	TheTestActive->FreePageUpdateTest();
  1.1040 +
  1.1041 +	CActiveScheduler::Start();
  1.1042 +	
  1.1043 +	delete TheTestActive;
  1.1044 +	TheTestActive = NULL;
  1.1045 +	delete scheduler;
  1.1046 +	}
  1.1047 +
  1.1048 +//////////////////////////////////////////////////////////////////////////////////////////////////
  1.1049 +
  1.1050 +//Usage: "t_sqlcompact2 [<drive letter>:]"
  1.1051 +
  1.1052 +TInt E32Main()
  1.1053 +	{
  1.1054 +	TheTest.Title();
  1.1055 +	
  1.1056 +	TheTrapCleanup = CTrapCleanup::New ();
  1.1057 +	__ASSERT_ALWAYS(TheTrapCleanup != NULL, User::Invariant());
  1.1058 +
  1.1059 +	__UHEAP_MARK;
  1.1060 +
  1.1061 +	User::CommandLine(TheCmd);
  1.1062 +	TheCmd.TrimAll();
  1.1063 +	if(TheCmd.Length() > 0)
  1.1064 +		{
  1.1065 +		TheDriveName.Copy(TheCmd);
  1.1066 +		}
  1.1067 +
  1.1068 +	_LIT(KDbName, "c:\\test\\t_sqlcompact2_1.db");
  1.1069 +	TheParse.Set(TheDriveName, &KDbName, 0);
  1.1070 +	const TDesC& dbFilePath = TheParse.FullName();
  1.1071 +	TheDbName.Copy(dbFilePath);
  1.1072 +	
  1.1073 +	TestEnvCreate();
  1.1074 +	
  1.1075 +	DoTests();
  1.1076 +
  1.1077 +	TestEnvDestroy();
  1.1078 +	
  1.1079 +	__UHEAP_MARKEND;
  1.1080 +
  1.1081 +	TheTest.End();
  1.1082 +	TheTest.Close();
  1.1083 +
  1.1084 +	delete TheTrapCleanup;
  1.1085 +
  1.1086 +	return KErrNone;
  1.1087 +	}