os/persistentdata/persistentstorage/sql/TEST/t_sqlcompact4.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200 (2014-06-10)
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <e32test.h>
sl@0
    17
#include <bautils.h>
sl@0
    18
#include <sqldb.h>
sl@0
    19
#include <stdlib.h>
sl@0
    20
#include "sqlite3.h"
sl@0
    21
#include "SqliteSymbian.h"
sl@0
    22
#include "SqlResourceTester.h"
sl@0
    23
sl@0
    24
///////////////////////////////////////////////////////////////////////////////////////
sl@0
    25
sl@0
    26
RTest TheTest(_L("t_sqlcompact4 test"));
sl@0
    27
TParse TheParse;
sl@0
    28
TDriveName TheDrive;
sl@0
    29
sl@0
    30
RSqlDatabase TheDb;
sl@0
    31
sqlite3* TheSqliteDb = NULL;
sl@0
    32
TBuf<256> TheCmd;
sl@0
    33
sl@0
    34
const TInt KTextLen = 1000;
sl@0
    35
const TInt KRecLen = 2000;
sl@0
    36
sl@0
    37
TBuf<KTextLen> TheText;
sl@0
    38
TBuf8<KRecLen> TheSqlQuery;
sl@0
    39
TBuf8<KRecLen> TheSqlFmt;
sl@0
    40
TBuf<KTextLen + 50> TheSqlTexLen;
sl@0
    41
sl@0
    42
_LIT(KDefaultDriveName, "c:");
sl@0
    43
_LIT(KTestDir, "c:\\test\\");
sl@0
    44
_LIT(KTestDbTemplate8, "c:\\test\\t_sqlcompact4_tmpl8.dat");
sl@0
    45
_LIT(KTestDbTemplate16, "c:\\test\\t_sqlcompact4_tmpl16.dat");
sl@0
    46
_LIT(KDbName, "c:\\test\\t_sqlcompact4_1.db");
sl@0
    47
_LIT(KDbName2, "c:\\test\\t_sqlcompact4_2.db");
sl@0
    48
_LIT(KRoDbName, "z:\\test\\testdb1.db");//Created outside the test app
sl@0
    49
TFileName TheTestDbName;
sl@0
    50
sl@0
    51
const TInt KMaxThreadCount = 100;
sl@0
    52
TInt32 TheTestThreadCount = 8;
sl@0
    53
sl@0
    54
const TInt KTestDbPageSize = 1024;
sl@0
    55
sl@0
    56
TInt TheOriginalDbSize8 = -1;
sl@0
    57
TInt TheCompactedDbSize8 = -1;
sl@0
    58
sl@0
    59
TInt TheOriginalDbSize16 = -1;
sl@0
    60
TInt TheCompactedDbSize16 = -1;
sl@0
    61
sl@0
    62
//In order to be able to compile the test, the following variables are defined (used inside the OS porting layer, when _SQLPROFILER macro is defined)
sl@0
    63
#ifdef _SQLPROFILER
sl@0
    64
TInt TheSqlSrvProfilerFileRead = 0;
sl@0
    65
TInt TheSqlSrvProfilerFileWrite = 0;
sl@0
    66
TInt TheSqlSrvProfilerFileSync = 0;
sl@0
    67
TInt TheSqlSrvProfilerFileSetSize = 0;
sl@0
    68
#endif
sl@0
    69
sl@0
    70
///////////////////////////////////////////////////////////////////////////////////////
sl@0
    71
sl@0
    72
void DestroyTestEnv()
sl@0
    73
	{
sl@0
    74
	if(TheSqliteDb)
sl@0
    75
		{
sl@0
    76
		sqlite3_close(TheSqliteDb);
sl@0
    77
		TheSqliteDb = NULL;
sl@0
    78
		}
sl@0
    79
	TheDb.Close();
sl@0
    80
	(void)RSqlDatabase::Delete(KDbName2);
sl@0
    81
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
    82
	(void)RSqlDatabase::Delete(KTestDbTemplate16);
sl@0
    83
	(void)RSqlDatabase::Delete(KTestDbTemplate8);
sl@0
    84
	sqlite3SymbianLibFinalize();
sl@0
    85
	CloseSTDLIB();
sl@0
    86
	}
sl@0
    87
sl@0
    88
///////////////////////////////////////////////////////////////////////////////////////
sl@0
    89
///////////////////////////////////////////////////////////////////////////////////////
sl@0
    90
//Test macros and functions
sl@0
    91
void Check(TInt aValue, TInt aLine)
sl@0
    92
	{
sl@0
    93
	if(!aValue)
sl@0
    94
		{
sl@0
    95
		DestroyTestEnv();
sl@0
    96
		RDebug::Print(_L("*** Test failure. Boolean expression evaluates to false.\r\n"));
sl@0
    97
		TheTest(EFalse, aLine);
sl@0
    98
		}
sl@0
    99
	}
sl@0
   100
void Check(TInt aValue, TInt aExpected, TInt aLine)
sl@0
   101
	{
sl@0
   102
	if(aValue != aExpected)
sl@0
   103
		{
sl@0
   104
		DestroyTestEnv();
sl@0
   105
		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
sl@0
   106
		TheTest(EFalse, aLine);
sl@0
   107
		}
sl@0
   108
	}
sl@0
   109
#define TEST(arg) ::Check((arg), __LINE__)
sl@0
   110
#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
sl@0
   111
sl@0
   112
///////////////////////////////////////////////////////////////////////////////////////
sl@0
   113
sl@0
   114
void CreateTestEnv()
sl@0
   115
    {
sl@0
   116
    RFs fs;
sl@0
   117
	TInt err = fs.Connect();
sl@0
   118
	TEST2(err, KErrNone);
sl@0
   119
sl@0
   120
	err = fs.MkDir(KTestDir);
sl@0
   121
	TEST(err == KErrNone || err == KErrAlreadyExists);
sl@0
   122
sl@0
   123
	TheParse.Set(TheDrive, &KTestDir, 0);
sl@0
   124
sl@0
   125
	err = fs.MkDir(TheParse.DriveAndPath());
sl@0
   126
	TEST(err == KErrNone || err == KErrAlreadyExists);
sl@0
   127
sl@0
   128
	fs.Close();
sl@0
   129
sl@0
   130
	sqlite3SymbianLibInit();
sl@0
   131
	}
sl@0
   132
sl@0
   133
///////////////////////////////////////////////////////////////////////////////////////
sl@0
   134
sl@0
   135
void CreateTestDatabase8()
sl@0
   136
	{
sl@0
   137
	TheTest.Printf(_L("Create UTF8 test database: %S\r\n"), &KTestDbTemplate8);
sl@0
   138
	(void)RSqlDatabase::Delete(KTestDbTemplate8);
sl@0
   139
	TBuf8<KMaxFileName> fname;
sl@0
   140
	fname.Copy(KTestDbTemplate8);
sl@0
   141
	TheSqliteDb = NULL;
sl@0
   142
	TInt rc = sqlite3_open((const char*)fname.PtrZ(), &TheSqliteDb);
sl@0
   143
	TEST2(rc, SQLITE_OK);
sl@0
   144
	TBuf8<100> sql;
sl@0
   145
	_LIT8(KSql, "PRAGMA page_size=%d\x0");
sl@0
   146
	sql.Format(KSql, KTestDbPageSize);
sl@0
   147
	rc = sqlite3_exec(TheSqliteDb, (const char*)sql.Ptr(), 0, 0, 0);
sl@0
   148
	TEST2(rc, SQLITE_OK);
sl@0
   149
	rc = sqlite3_exec(TheSqliteDb, "CREATE TABLE A(Id INTEGER,Data BLOB)", 0, 0, 0);
sl@0
   150
	TEST2(rc, SQLITE_OK);
sl@0
   151
	//Insert records
sl@0
   152
	rc = sqlite3_exec(TheSqliteDb, "BEGIN", 0, 0, 0);
sl@0
   153
	TEST2(rc, SQLITE_OK);
sl@0
   154
	TheSqlQuery.Copy(_L8("INSERT INTO A VALUES(%d,x'"));
sl@0
   155
	for(TInt j=0;j<(KRecLen-50);++j)
sl@0
   156
		{
sl@0
   157
		TheSqlQuery.Append(_L8("A"));
sl@0
   158
		}
sl@0
   159
	TheSqlQuery.Append(_L8("')"));
sl@0
   160
	const TInt KRecCount = 100;	
sl@0
   161
	for(TInt i=0;i<KRecCount;++i)
sl@0
   162
		{
sl@0
   163
		TheSqlFmt.Format(TheSqlQuery, i + 1);
sl@0
   164
		rc = sqlite3_exec(TheSqliteDb, (const char*)TheSqlFmt.PtrZ(), 0, 0, 0);
sl@0
   165
		TEST2(rc, SQLITE_OK);
sl@0
   166
		}
sl@0
   167
	rc = sqlite3_exec(TheSqliteDb, "COMMIT", 0, 0, 0);
sl@0
   168
	TEST2(rc, SQLITE_OK);
sl@0
   169
	//Free some space
sl@0
   170
	rc = sqlite3_exec(TheSqliteDb, "DELETE FROM A WHERE Id > 10", 0, 0, 0);
sl@0
   171
	TEST2(rc, SQLITE_OK);
sl@0
   172
	sqlite3_close(TheSqliteDb);
sl@0
   173
	TheSqliteDb = NULL;
sl@0
   174
	}
sl@0
   175
sl@0
   176
void CreateTestDatabase16()
sl@0
   177
	{
sl@0
   178
	TheTest.Printf(_L("Create UTF16 test database: %S\r\n"), &KTestDbTemplate16);
sl@0
   179
	(void)RSqlDatabase::Delete(KTestDbTemplate16);
sl@0
   180
	TBuf<KMaxFileName> fname;
sl@0
   181
	fname.Copy(KTestDbTemplate16);
sl@0
   182
	TheSqliteDb = NULL;
sl@0
   183
	TInt rc = sqlite3_open16(fname.PtrZ(), &TheSqliteDb);
sl@0
   184
	TEST2(rc, SQLITE_OK);
sl@0
   185
	TBuf8<100> sql;
sl@0
   186
	_LIT8(KSql, "PRAGMA page_size=%d\x0");
sl@0
   187
	sql.Format(KSql, KTestDbPageSize);
sl@0
   188
	rc = sqlite3_exec(TheSqliteDb, (const char*)sql.Ptr(), 0, 0, 0);
sl@0
   189
	TEST2(rc, SQLITE_OK);
sl@0
   190
	rc = sqlite3_exec(TheSqliteDb, "CREATE TABLE A(Id INTEGER,Data BLOB)", 0, 0, 0);
sl@0
   191
	TEST2(rc, SQLITE_OK);
sl@0
   192
	//Insert records
sl@0
   193
	rc = sqlite3_exec(TheSqliteDb, "BEGIN", 0, 0, 0);
sl@0
   194
	TEST2(rc, SQLITE_OK);
sl@0
   195
	TheSqlQuery.Copy(_L8("INSERT INTO A VALUES(%d,x'"));
sl@0
   196
	for(TInt j=0;j<(KRecLen-50);++j)
sl@0
   197
		{
sl@0
   198
		TheSqlQuery.Append(_L8("A"));
sl@0
   199
		}
sl@0
   200
	TheSqlQuery.Append(_L8("')"));
sl@0
   201
	const TInt KRecCount = 100;	
sl@0
   202
	for(TInt i=0;i<KRecCount;++i)
sl@0
   203
		{
sl@0
   204
		TheSqlFmt.Format(TheSqlQuery, i + 1);
sl@0
   205
		rc = sqlite3_exec(TheSqliteDb, (const char*)TheSqlFmt.PtrZ(), 0, 0, 0);
sl@0
   206
		TEST2(rc, SQLITE_OK);
sl@0
   207
		}
sl@0
   208
	rc = sqlite3_exec(TheSqliteDb, "COMMIT", 0, 0, 0);
sl@0
   209
	TEST2(rc, SQLITE_OK);
sl@0
   210
	//Free some space
sl@0
   211
	rc = sqlite3_exec(TheSqliteDb, "DELETE FROM A WHERE Id > 10", 0, 0, 0);
sl@0
   212
	TEST2(rc, SQLITE_OK);
sl@0
   213
	sqlite3_close(TheSqliteDb);
sl@0
   214
	TheSqliteDb = NULL;
sl@0
   215
	}
sl@0
   216
	
sl@0
   217
void CreateDatabase8(const TDesC& aTargetDbName)
sl@0
   218
	{
sl@0
   219
	RFs fs;
sl@0
   220
	TInt err = fs.Connect();
sl@0
   221
	TEST2(err, KErrNone);		
sl@0
   222
	CFileMan* fm = NULL;
sl@0
   223
	TRAP(err, fm = CFileMan::NewL(fs));
sl@0
   224
	TEST2(err, KErrNone);
sl@0
   225
	err = fm->Copy(KTestDbTemplate8, aTargetDbName);
sl@0
   226
	delete fm;
sl@0
   227
	fs.Close();
sl@0
   228
	TEST2(err, KErrNone);
sl@0
   229
	}
sl@0
   230
sl@0
   231
void CreateDatabase16(const TDesC& aTargetDbName)
sl@0
   232
	{
sl@0
   233
	RFs fs;
sl@0
   234
	TInt err = fs.Connect();
sl@0
   235
	TEST2(err, KErrNone);		
sl@0
   236
	CFileMan* fm = NULL;
sl@0
   237
	TRAP(err, fm = CFileMan::NewL(fs));
sl@0
   238
	TEST2(err, KErrNone);
sl@0
   239
	err = fm->Copy(KTestDbTemplate16, aTargetDbName);
sl@0
   240
	delete fm;
sl@0
   241
	fs.Close();
sl@0
   242
	TEST2(err, KErrNone);
sl@0
   243
	}
sl@0
   244
sl@0
   245
void CalculateMaxCompaction8()
sl@0
   246
	{
sl@0
   247
	TheTest.Printf(_L("UTF8 test database - calculate max compaction\r\n"));
sl@0
   248
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   249
	CreateDatabase8(TheTestDbName);
sl@0
   250
	TInt err = TheDb.Open(TheTestDbName);
sl@0
   251
	TEST2(err, KErrNone);
sl@0
   252
	RSqlDatabase::TSize size1;
sl@0
   253
	err = TheDb.Size(size1);
sl@0
   254
	TEST2(err, KErrNone);
sl@0
   255
	TheTest.Printf(_L("UTF8.Database before compaction: size %ld, free space %ld\r\n"), size1.iSize, size1.iFree);
sl@0
   256
	err = TheDb.Compact(RSqlDatabase::EMaxCompaction);
sl@0
   257
	TEST2(err, size1.iFree);
sl@0
   258
	RSqlDatabase::TSize size2;
sl@0
   259
	err = TheDb.Size(size2);
sl@0
   260
	TEST2(err, KErrNone);
sl@0
   261
	TheTest.Printf(_L("UTF8.Database after compaction: size %ld, free space %ld\r\n"), size2.iSize, size2.iFree);
sl@0
   262
	TheDb.Close();
sl@0
   263
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   264
	TheOriginalDbSize8 = size1.iSize;
sl@0
   265
	TheCompactedDbSize8 = size2.iSize;
sl@0
   266
	TEST(TheOriginalDbSize8 > 0);
sl@0
   267
	TEST(TheCompactedDbSize8 > 0 && TheCompactedDbSize8 < TheOriginalDbSize8);
sl@0
   268
	}
sl@0
   269
sl@0
   270
void CalculateMaxCompaction16()
sl@0
   271
	{
sl@0
   272
	TheTest.Printf(_L("UTF16 test database - calculate max compaction\r\n"));
sl@0
   273
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   274
	CreateDatabase16(TheTestDbName);
sl@0
   275
	TInt err = TheDb.Open(TheTestDbName);
sl@0
   276
	TEST2(err, KErrNone);
sl@0
   277
	RSqlDatabase::TSize size1;
sl@0
   278
	err = TheDb.Size(size1);
sl@0
   279
	TEST2(err, KErrNone);
sl@0
   280
	TheTest.Printf(_L("UTF16.Database before compaction: size %ld, free space %ld\r\n"), size1.iSize, size1.iFree);
sl@0
   281
	err = TheDb.Compact(RSqlDatabase::EMaxCompaction);
sl@0
   282
	TEST2(err, size1.iFree);
sl@0
   283
	RSqlDatabase::TSize size2;
sl@0
   284
	err = TheDb.Size(size2);
sl@0
   285
	TEST2(err, KErrNone);
sl@0
   286
	TheTest.Printf(_L("UTF16.Database after compaction: size %ld, free space %ld\r\n"), size2.iSize, size2.iFree);
sl@0
   287
	TheDb.Close();
sl@0
   288
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   289
	TheOriginalDbSize16 = size1.iSize;
sl@0
   290
	TheCompactedDbSize16 = size2.iSize;
sl@0
   291
	TEST(TheOriginalDbSize16 > 0);
sl@0
   292
	TEST(TheCompactedDbSize16 > 0 && TheCompactedDbSize16 < TheOriginalDbSize16);
sl@0
   293
	}
sl@0
   294
sl@0
   295
///////////////////////////////////////////////////////////////////////////////////////
sl@0
   296
sl@0
   297
sl@0
   298
enum TCompactionType {ESyncCompaction, EAsyncCompaction, EMaxCompactionType};
sl@0
   299
sl@0
   300
TInt DoCompact(TCompactionType aType, TInt aSize, const TDesC& aAttachDbName = KNullDesC)
sl@0
   301
	{
sl@0
   302
	TInt err = KErrGeneral;
sl@0
   303
	switch(aType)
sl@0
   304
		{
sl@0
   305
		case ESyncCompaction:
sl@0
   306
			err = TheDb.Compact(aSize, aAttachDbName);
sl@0
   307
			break;
sl@0
   308
		case EAsyncCompaction:
sl@0
   309
			{
sl@0
   310
			TRequestStatus stat;				
sl@0
   311
			TheDb.Compact(aSize, stat, aAttachDbName);
sl@0
   312
			User::WaitForRequest(stat);
sl@0
   313
			TEST(stat != KRequestPending);
sl@0
   314
			err = stat.Int();
sl@0
   315
			break;
sl@0
   316
			}
sl@0
   317
		default:
sl@0
   318
			TEST(0);
sl@0
   319
			break;	
sl@0
   320
		}
sl@0
   321
	return err;
sl@0
   322
	}
sl@0
   323
sl@0
   324
TInt DoManualCompaction(TCompactionType aType, const TDesC& aMainDb, TInt aSize, TBool aRoFlag = EFalse)
sl@0
   325
	{
sl@0
   326
	if(!aRoFlag)
sl@0
   327
		{
sl@0
   328
		(void)RSqlDatabase::Delete(aMainDb);
sl@0
   329
		CreateDatabase8(aMainDb);
sl@0
   330
		}
sl@0
   331
sl@0
   332
	TInt err = TheDb.Open(aMainDb);
sl@0
   333
	TEST2(err, KErrNone);
sl@0
   334
	
sl@0
   335
	err = DoCompact(aType, aSize);
sl@0
   336
		
sl@0
   337
	TheDb.Close();
sl@0
   338
	if(!aRoFlag)
sl@0
   339
		{
sl@0
   340
		(void)RSqlDatabase::Delete(aMainDb);
sl@0
   341
		}
sl@0
   342
	return err;
sl@0
   343
	}
sl@0
   344
sl@0
   345
TInt DoManualCompaction(TCompactionType aType, TInt aSize, const TDesC& aAttachDbName)
sl@0
   346
	{
sl@0
   347
	return DoCompact(aType, aSize, aAttachDbName);
sl@0
   348
	}
sl@0
   349
sl@0
   350
void DoManualCompaction(TCompactionType aType, TInt aSize, TInt aCompactedSize)
sl@0
   351
	{
sl@0
   352
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   353
	CreateDatabase8(TheTestDbName);
sl@0
   354
sl@0
   355
	TInt err = TheDb.Open(TheTestDbName);
sl@0
   356
	TEST2(err, KErrNone);
sl@0
   357
	
sl@0
   358
	err = DoCompact(aType, aSize);
sl@0
   359
	TEST(err >= 0);
sl@0
   360
	
sl@0
   361
	RSqlDatabase::TSize size;
sl@0
   362
	err = TheDb.Size(size);
sl@0
   363
	TEST2(err, KErrNone);
sl@0
   364
	TEST2(size.iSize, aCompactedSize);
sl@0
   365
		
sl@0
   366
	TheDb.Close();
sl@0
   367
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   368
	}
sl@0
   369
sl@0
   370
void DoManualCompaction(TCompactionType aType, TInt aSize, TInt aCompactedSize, const TDesC& aAttachDbName)
sl@0
   371
	{
sl@0
   372
	TInt err = DoCompact(aType, aSize, aAttachDbName);
sl@0
   373
	TEST(err >= 0);
sl@0
   374
	
sl@0
   375
	RSqlDatabase::TSize size;
sl@0
   376
	err = TheDb.Size(size, aAttachDbName);
sl@0
   377
	TEST2(err, KErrNone);
sl@0
   378
	TEST2(size.iSize, aCompactedSize);
sl@0
   379
	}
sl@0
   380
sl@0
   381
/**
sl@0
   382
@SYMTestCaseID			SYSLIB-SQL-UT-4064
sl@0
   383
@SYMTestCaseDesc		Manual compaction - negative tests.
sl@0
   384
						The test creates a database with a manual compaction mode.
sl@0
   385
						Then the test executes the following negative tests using both synchronous and
sl@0
   386
						asynchronous Compact() methods:
sl@0
   387
							- RSqlDatabase::Compact() called with aSize parameter value = KMinTInt;
sl@0
   388
							- RSqlDatabase::Compact() called with negative aSize parameter value;
sl@0
   389
							- RSqlDatabase::Compact() called on a read-only database;
sl@0
   390
							- RSqlDatabase::Compact() called on an attached read-only database;
sl@0
   391
							- RSqlDatabase::Compact() called on a nonexisting attached database with very long name;
sl@0
   392
							- RSqlDatabase::Compact() called with aSize = 0;
sl@0
   393
							- RSqlDatabase::Compact() called on a read-only database where the version number of symbian_settings table is 3;
sl@0
   394
@SYMTestPriority		Medium
sl@0
   395
@SYMTestActions			Manual compaction - negative tests.
sl@0
   396
@SYMTestExpectedResults Test must not fail
sl@0
   397
@SYMREQ					REQ10273
sl@0
   398
                        REQ10274
sl@0
   399
                        REQ10402
sl@0
   400
*/
sl@0
   401
void ManualCompactionNegativeTest()
sl@0
   402
	{
sl@0
   403
	for(TInt i=0;i<EMaxCompactionType;++i)
sl@0
   404
		{
sl@0
   405
		//Specifying KMaxTInt as aSize argument value.
sl@0
   406
		TInt err = DoManualCompaction((TCompactionType)i, TheTestDbName, KMaxTInt);
sl@0
   407
		TEST(err > 0);
sl@0
   408
		//Specifying KMinTInt as aSize argument value.
sl@0
   409
		err = DoManualCompaction((TCompactionType)i, TheTestDbName, KMinTInt);
sl@0
   410
		TEST2(err, KErrArgument);
sl@0
   411
		//Specifying another negative value as aSize argument value.
sl@0
   412
		err = DoManualCompaction((TCompactionType)i, TheTestDbName, -357);
sl@0
   413
		TEST2(err, KErrArgument);
sl@0
   414
		//Specifying zero as aSize argument value.
sl@0
   415
		err = DoManualCompaction((TCompactionType)i, TheTestDbName, 0);
sl@0
   416
		TEST2(err, 0);
sl@0
   417
		//Read-only database - old format (version 3 of symbian_settings table)
sl@0
   418
		err = DoManualCompaction((TCompactionType)i, KRoDbName, RSqlDatabase::EMaxCompaction, ETrue);
sl@0
   419
		TEST2(err, KSqlErrReadOnly);
sl@0
   420
		//
sl@0
   421
		(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   422
		CreateDatabase16(TheTestDbName);
sl@0
   423
		err = TheDb.Open(TheTestDbName);
sl@0
   424
		TEST2(err, KErrNone);
sl@0
   425
		_LIT(KAttachDbName, "Db");
sl@0
   426
		//Attached read-only database
sl@0
   427
		err = TheDb.Attach(KRoDbName, KAttachDbName);
sl@0
   428
		TEST2(err, KErrNone);
sl@0
   429
		err = DoManualCompaction((TCompactionType)i, RSqlDatabase::EMaxCompaction, KAttachDbName);
sl@0
   430
		TEST2(err, KSqlErrReadOnly);
sl@0
   431
		err = TheDb.Detach(KAttachDbName);
sl@0
   432
		TEST2(err, KErrNone);
sl@0
   433
		//Nonexisting attached database 
sl@0
   434
		err = DoManualCompaction((TCompactionType)i, RSqlDatabase::EMaxCompaction, _L("aaa"));
sl@0
   435
		TEST2(err, KSqlErrGeneral);
sl@0
   436
        //Very long name of a  nonexisting attached database 
sl@0
   437
        TBuf<KMaxFileName + 10> fname;
sl@0
   438
        fname.SetLength(fname.MaxLength());
sl@0
   439
        fname.Fill(0xDD);
sl@0
   440
        err = DoManualCompaction((TCompactionType)i, RSqlDatabase::EMaxCompaction, fname);
sl@0
   441
        TEST2(err, KErrBadName);
sl@0
   442
        //Invalid attached database name 
sl@0
   443
        fname.Copy(_L("c:\\|aaa|.db"));
sl@0
   444
        err = DoManualCompaction((TCompactionType)i, RSqlDatabase::EMaxCompaction, fname);
sl@0
   445
        TEST2(err, KSqlErrGeneral);
sl@0
   446
        //
sl@0
   447
		TheDb.Close();
sl@0
   448
		(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   449
		}
sl@0
   450
	}
sl@0
   451
sl@0
   452
/**
sl@0
   453
@SYMTestCaseID			SYSLIB-SQL-UT-4065
sl@0
   454
@SYMTestCaseDesc		Manual compaction - functional tests.
sl@0
   455
						The test creates a database with a manual compaction mode.
sl@0
   456
						Then the test executes the following functional tests using both synchronous and
sl@0
   457
						asynchronous Compact() methods:
sl@0
   458
							- RSqlDatabase::Compact() called with aSize parameter value = RSqlDatabase::EMaxCompaction;
sl@0
   459
							- RSqlDatabase::Compact() called with aSize parameter value = 0. No pages should be removed;
sl@0
   460
							- RSqlDatabase::Compact() called with aSize parameter value = 1. 1 page should be removed;
sl@0
   461
							- RSqlDatabase::Compact() called with aSize parameter value = "db page size - 1". 1 page should be removed;
sl@0
   462
							- RSqlDatabase::Compact() called with aSize parameter value = "db page size * <cnt>". <cnt> pages should be removed;
sl@0
   463
							- RSqlDatabase::Compact() called with aSize parameter value > the free db space. All free pages should be removed;
sl@0
   464
						The same functional tests are repeated with an attached database.
sl@0
   465
@SYMTestPriority		Medium
sl@0
   466
@SYMTestActions			Manual compaction - functional tests.
sl@0
   467
@SYMTestExpectedResults Test must not fail
sl@0
   468
@SYMREQ					REQ10273
sl@0
   469
                        REQ10274
sl@0
   470
                        REQ10402
sl@0
   471
*/
sl@0
   472
void ManualCompactionTest()
sl@0
   473
	{
sl@0
   474
	for(TInt i=0;i<EMaxCompactionType;++i)
sl@0
   475
		{
sl@0
   476
		//Calling Compact() with aSize = RSqlDatabase::EMaxCompaction
sl@0
   477
		DoManualCompaction((TCompactionType)i, RSqlDatabase::EMaxCompaction, TheCompactedDbSize8);
sl@0
   478
		//Calling Compact() with aSize = 0. 0 pages expected to be removed
sl@0
   479
		DoManualCompaction((TCompactionType)i, 0, TheOriginalDbSize8);
sl@0
   480
		//Calling Compact() with aSize = 1. 1 page expected to be removed
sl@0
   481
		DoManualCompaction((TCompactionType)i, 1, TheOriginalDbSize8 - KTestDbPageSize);
sl@0
   482
		//Calling Compact() with aSize = KTestDbPageSize - 1. 1 page expected to be removed
sl@0
   483
		DoManualCompaction((TCompactionType)i, KTestDbPageSize - 1, TheOriginalDbSize8 - KTestDbPageSize);
sl@0
   484
		//Calling Compact() with aSize = KTestDbPageSize. 1 page expected to be removed
sl@0
   485
		DoManualCompaction((TCompactionType)i, KTestDbPageSize, TheOriginalDbSize8 - KTestDbPageSize);
sl@0
   486
		const TInt KPagesCnt1 = 17;
sl@0
   487
		//Calling Compact() with aSize = KTestDbPageSize * KPagesCnt1. KPagesCnt1 pages expected to be removed
sl@0
   488
		DoManualCompaction((TCompactionType)i, KTestDbPageSize * KPagesCnt1, TheOriginalDbSize8 - KTestDbPageSize * KPagesCnt1);
sl@0
   489
		//Calling Compact() with aSize > TheOriginalDbSize8. All free pages expected to be removed
sl@0
   490
		DoManualCompaction((TCompactionType)i, TheOriginalDbSize8 + 2000, TheCompactedDbSize8);
sl@0
   491
		//Attached database
sl@0
   492
		(void)RSqlDatabase::Delete(KDbName2);
sl@0
   493
		TInt err = TheDb.Create(KDbName2);
sl@0
   494
		TEST2(err, KErrNone);
sl@0
   495
		(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   496
		CreateDatabase16(TheTestDbName);
sl@0
   497
		_LIT(KAttachDbName, "Db");
sl@0
   498
		err = TheDb.Attach(TheTestDbName, KAttachDbName);
sl@0
   499
		TEST2(err, KErrNone);
sl@0
   500
		TInt newDatabaseSize = TheOriginalDbSize16;
sl@0
   501
		//Calling Compact() with aSize = 0. 0 pages expected to be removed
sl@0
   502
		DoManualCompaction((TCompactionType)i, 0, newDatabaseSize, KAttachDbName);
sl@0
   503
		//Calling Compact() with aSize = 1. 1 page expected to be removed
sl@0
   504
		DoManualCompaction((TCompactionType)i, 1, TheOriginalDbSize16 - KTestDbPageSize, KAttachDbName);
sl@0
   505
		newDatabaseSize -= KTestDbPageSize;
sl@0
   506
		//Calling Compact() with aSize = KTestDbPageSize - 1. 1 page expected to be removed
sl@0
   507
		DoManualCompaction((TCompactionType)i, KTestDbPageSize - 1, newDatabaseSize - KTestDbPageSize, KAttachDbName);
sl@0
   508
		newDatabaseSize -= KTestDbPageSize;
sl@0
   509
		//Calling Compact() with aSize = KTestDbPageSize. 1 page expected to be removed
sl@0
   510
		DoManualCompaction((TCompactionType)i, KTestDbPageSize, newDatabaseSize - KTestDbPageSize, KAttachDbName);
sl@0
   511
		newDatabaseSize -= KTestDbPageSize;
sl@0
   512
		//Calling Compact() with aSize = KTestDbPageSize * KPagesCnt1. KPagesCnt1 pages expected to be removed
sl@0
   513
		DoManualCompaction((TCompactionType)i, KTestDbPageSize * KPagesCnt1, newDatabaseSize - KTestDbPageSize * KPagesCnt1, KAttachDbName);
sl@0
   514
		newDatabaseSize -= KTestDbPageSize * KPagesCnt1;
sl@0
   515
		//Calling Compact() with aSize > newDatabaseSize. All free pages expected to be removed
sl@0
   516
		DoManualCompaction((TCompactionType)i, newDatabaseSize + 2000, TheCompactedDbSize16, KAttachDbName);
sl@0
   517
		//
sl@0
   518
		err = TheDb.Detach(KAttachDbName);
sl@0
   519
		TEST2(err, KErrNone);
sl@0
   520
		TheDb.Close();
sl@0
   521
		(void)RSqlDatabase::Delete(KDbName2);
sl@0
   522
		}
sl@0
   523
	}
sl@0
   524
sl@0
   525
sl@0
   526
enum TSizeTestType {EManualSizeTest, EAutoSizeTest};
sl@0
   527
sl@0
   528
void DoCompactionDbSizeTest(TSizeTestType aType)
sl@0
   529
	{
sl@0
   530
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   531
	_LIT8(KConfig1, "compaction=manual");
sl@0
   532
	_LIT8(KConfig2, "compaction=auto");
sl@0
   533
	TInt err = TheDb.Create(TheTestDbName, aType == EManualSizeTest ? &KConfig1 : &KConfig2);
sl@0
   534
	TEST2(err, KErrNone);
sl@0
   535
	err = TheDb.Exec(_L("CREATE TABLE A(T TEXT)"));
sl@0
   536
	TEST2(err, 1);
sl@0
   537
	//
sl@0
   538
	RSqlDatabase::TSize size;
sl@0
   539
	err = TheDb.Size(size);
sl@0
   540
	TEST2(err, KErrNone);
sl@0
   541
	TEST2(size.iFree, 0);
sl@0
   542
	//
sl@0
   543
	const TInt KRecCnt = 50;
sl@0
   544
	for(TInt i=0;i<KRecCnt;++i)
sl@0
   545
		{
sl@0
   546
		err = TheDb.Exec(_L("INSERT INTO A VALUES('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaa')"));
sl@0
   547
		TEST2(err, 1);
sl@0
   548
		}
sl@0
   549
	//
sl@0
   550
	err = TheDb.Size(size);
sl@0
   551
	TEST2(err, KErrNone);
sl@0
   552
	TEST2(size.iFree, 0);
sl@0
   553
	//
sl@0
   554
	err = TheDb.Exec(_L("DELETE FROM A WHERE 1"));
sl@0
   555
	TEST2(err, KRecCnt);
sl@0
   556
	//
sl@0
   557
	err = TheDb.Size(size);
sl@0
   558
	TEST2(err, KErrNone);
sl@0
   559
	if(aType == EManualSizeTest)
sl@0
   560
		{
sl@0
   561
		TEST(size.iFree > 0);
sl@0
   562
		}
sl@0
   563
	else
sl@0
   564
		{
sl@0
   565
		TEST2(size.iFree, 0);
sl@0
   566
		}
sl@0
   567
	//
sl@0
   568
	TheDb.Close();
sl@0
   569
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   570
	}
sl@0
   571
sl@0
   572
/**
sl@0
   573
@SYMTestCaseID			SYSLIB-SQL-UT-4066
sl@0
   574
@SYMTestCaseDesc		RSqlDatabase::Size(TSize&) called on a database with manual compaction mode.
sl@0
   575
						The test creates a database with a manual compaction mode.
sl@0
   576
						Then the test inserts some records and deletes the records making some free database pages.
sl@0
   577
						The test calls RSqlDatabase::Size(TSize&) before and after the delete operation and verifies
sl@0
   578
						that the database file size stays unchanged.
sl@0
   579
@SYMTestPriority		Medium
sl@0
   580
@SYMTestActions			RSqlDatabase::Size(TSize&) called on a database with manual compaction mode.
sl@0
   581
@SYMTestExpectedResults Test must not fail
sl@0
   582
@SYMREQ					REQ10407
sl@0
   583
*/
sl@0
   584
void ManualCompactionSizeTest()
sl@0
   585
	{
sl@0
   586
	DoCompactionDbSizeTest(EManualSizeTest);
sl@0
   587
	}
sl@0
   588
sl@0
   589
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
   590
//////////////////////////////////         OOM testing        ////////////////////////////////////////////////////////////
sl@0
   591
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
   592
sl@0
   593
void PrintEndOfOomTest(TInt aFailingAllocationNo)
sl@0
   594
	{
sl@0
   595
	TheTest.Printf(_L("=== OOM Test succeeded at heap failure rate of %d ===\r\n"), aFailingAllocationNo);
sl@0
   596
	}
sl@0
   597
sl@0
   598
void SetDbHeapFailure(TInt aFailingAllocationNo)
sl@0
   599
	{
sl@0
   600
	const TInt KDelayedDbHeapFailureMask = 0x1000;
sl@0
   601
	TSqlResourceTester::SetDbHeapFailure(RHeap::EDeterministic | KDelayedDbHeapFailureMask, aFailingAllocationNo);
sl@0
   602
	}
sl@0
   603
	
sl@0
   604
void ResetDbHeapFailure()
sl@0
   605
	{
sl@0
   606
	TSqlResourceTester::SetDbHeapFailure(RHeap::ENone, 0);
sl@0
   607
	}
sl@0
   608
sl@0
   609
static TInt TheHandleCount1B;
sl@0
   610
static TInt TheHandleCount2B;
sl@0
   611
static TInt TheAllocatedCellsCountB;
sl@0
   612
sl@0
   613
void MarkHandles()
sl@0
   614
	{
sl@0
   615
	RThread().HandleCount(TheHandleCount1B, TheHandleCount2B);
sl@0
   616
	}
sl@0
   617
sl@0
   618
void CheckHandles()
sl@0
   619
	{
sl@0
   620
	TInt endHandleCount1E;
sl@0
   621
	TInt endHandleCount2E;
sl@0
   622
sl@0
   623
	RThread().HandleCount(endHandleCount1E, endHandleCount2E);
sl@0
   624
sl@0
   625
	TEST(TheHandleCount1B == endHandleCount1E);
sl@0
   626
	TEST(TheHandleCount2B == endHandleCount2E);
sl@0
   627
	}
sl@0
   628
sl@0
   629
void MarkAllocatedCells()
sl@0
   630
	{
sl@0
   631
	TheAllocatedCellsCountB = User::CountAllocCells();
sl@0
   632
	}
sl@0
   633
sl@0
   634
void CheckAllocatedCells()
sl@0
   635
	{
sl@0
   636
	TInt allocatedCellsCountE = User::CountAllocCells();
sl@0
   637
	TEST(allocatedCellsCountE == TheAllocatedCellsCountB);
sl@0
   638
	}
sl@0
   639
sl@0
   640
typedef void (*TDbFuncPtrL)(const TDesC& aDbName);
sl@0
   641
sl@0
   642
void DoManualCompactionOomTest(TDbFuncPtrL aTestFunctionPtrL, const TDesC& aDbFileName, const TDesC& aAttachDbFileName, const TDesC& aDbName)
sl@0
   643
	{
sl@0
   644
	const TInt KDoDbOomTestAllocLimitServer = 1000;
sl@0
   645
	TInt failingAllocation = 0;
sl@0
   646
	TInt allocation = 0;
sl@0
   647
	TInt err = KErrNoMemory;
sl@0
   648
	while(allocation < KDoDbOomTestAllocLimitServer)
sl@0
   649
		{
sl@0
   650
		MarkHandles();
sl@0
   651
		MarkAllocatedCells();
sl@0
   652
		
sl@0
   653
		__UHEAP_MARK;
sl@0
   654
sl@0
   655
		SetDbHeapFailure(++allocation);
sl@0
   656
sl@0
   657
		err = TheDb.Open(aDbFileName);
sl@0
   658
		TEST2(err, KErrNone);
sl@0
   659
		if(aAttachDbFileName != KNullDesC)
sl@0
   660
			{
sl@0
   661
			TEST(aDbName != KNullDesC);
sl@0
   662
			err = TheDb.Attach(aAttachDbFileName, aDbName);
sl@0
   663
			TEST(err == KErrNone || err == KErrNoMemory);
sl@0
   664
			}
sl@0
   665
		if(err == KErrNone)
sl@0
   666
			{
sl@0
   667
			TRAP(err, (*aTestFunctionPtrL)(aDbName));
sl@0
   668
			if(err != KErrNoMemory)
sl@0
   669
				{			
sl@0
   670
				TEST2(err, KErrNone);
sl@0
   671
				}
sl@0
   672
			else
sl@0
   673
				{
sl@0
   674
				failingAllocation = allocation;	
sl@0
   675
				}
sl@0
   676
			}
sl@0
   677
			
sl@0
   678
		ResetDbHeapFailure();
sl@0
   679
sl@0
   680
		if(aAttachDbFileName != KNullDesC)
sl@0
   681
			{
sl@0
   682
			(void)TheDb.Detach(aDbName);
sl@0
   683
			}
sl@0
   684
		TheDb.Close();
sl@0
   685
sl@0
   686
		__UHEAP_MARKEND;
sl@0
   687
sl@0
   688
		CheckAllocatedCells();	    	
sl@0
   689
		CheckHandles();	
sl@0
   690
		}
sl@0
   691
	TEST2(err, KErrNone);
sl@0
   692
	PrintEndOfOomTest(failingAllocation + 1);
sl@0
   693
	}
sl@0
   694
sl@0
   695
void OomTest1L(const TDesC&)
sl@0
   696
	{
sl@0
   697
	User::LeaveIfError(TheDb.Compact(RSqlDatabase::EMaxCompaction));
sl@0
   698
	}
sl@0
   699
sl@0
   700
void OomTest2L(const TDesC& aDbName)
sl@0
   701
	{
sl@0
   702
	TEST(aDbName != KNullDesC);
sl@0
   703
	User::LeaveIfError(TheDb.Compact(RSqlDatabase::EMaxCompaction, aDbName));
sl@0
   704
	}
sl@0
   705
sl@0
   706
/**
sl@0
   707
@SYMTestCaseID			SYSLIB-SQL-UT-4068
sl@0
   708
@SYMTestCaseDesc		RSqlDatabase::Compact() - OOM test.
sl@0
   709
						The test creates a database with a manual compaction mode.
sl@0
   710
						Then the test calls Compact() in an OOM loop.
sl@0
   711
						The same OOM test is repeated for Compact() called an attached database.
sl@0
   712
@SYMTestPriority		Medium
sl@0
   713
@SYMTestActions			RSqlDatabase::Compact() - OOM test.
sl@0
   714
@SYMTestExpectedResults Test must not fail
sl@0
   715
@SYMREQ					REQ10405
sl@0
   716
*/
sl@0
   717
void ManualCompactionOomTest()
sl@0
   718
	{
sl@0
   719
	TheTest.Printf(_L("Main database - manual compaction - OOM test\r\n"));
sl@0
   720
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   721
	CreateDatabase8(TheTestDbName);
sl@0
   722
	DoManualCompactionOomTest(&OomTest1L, TheTestDbName, KNullDesC, KNullDesC);
sl@0
   723
	TInt err = TheDb.Open(TheTestDbName);
sl@0
   724
	TEST2(err, KErrNone);
sl@0
   725
	RSqlDatabase::TSize size;
sl@0
   726
	err = TheDb.Size(size);
sl@0
   727
	TEST2(err, KErrNone);
sl@0
   728
	TEST2(size.iSize, TheCompactedDbSize8);
sl@0
   729
	TheDb.Close();
sl@0
   730
sl@0
   731
	TheTest.Printf(_L("Attached database - manual compaction - OOM test\r\n"));
sl@0
   732
	(void)RSqlDatabase::Delete(KDbName2);
sl@0
   733
	err = TheDb.Create(KDbName2);
sl@0
   734
	TEST2(err, KErrNone);
sl@0
   735
	TheDb.Close();
sl@0
   736
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   737
	CreateDatabase16(TheTestDbName);
sl@0
   738
	DoManualCompactionOomTest(&OomTest2L, KDbName2, TheTestDbName, _L("Db"));
sl@0
   739
	err = TheDb.Open(TheTestDbName);
sl@0
   740
	TEST2(err, KErrNone);
sl@0
   741
	err = TheDb.Size(size);
sl@0
   742
	TEST2(err, KErrNone);
sl@0
   743
	TEST2(size.iSize, TheCompactedDbSize16);
sl@0
   744
	TheDb.Close();
sl@0
   745
sl@0
   746
	(void)RSqlDatabase::Delete(KDbName2);
sl@0
   747
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   748
	}
sl@0
   749
sl@0
   750
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
   751
sl@0
   752
/**
sl@0
   753
@SYMTestCaseID			SYSLIB-SQL-UT-4067
sl@0
   754
@SYMTestCaseDesc		RSqlDatabase::Size(TSize&) called on a database with auto compaction mode.
sl@0
   755
						The test creates a database with an auto compaction mode.
sl@0
   756
						Then the test inserts some records and deletes the records.
sl@0
   757
						The test calls RSqlDatabase::Size(TSize&) after the delete operation and verifies
sl@0
   758
						that the database file does not contain any free pages.
sl@0
   759
@SYMTestPriority		Medium
sl@0
   760
@SYMTestActions			RSqlDatabase::Size(TSize&) called on a database with auto compaction mode.
sl@0
   761
@SYMTestExpectedResults Test must not fail
sl@0
   762
@SYMREQ					REQ10407
sl@0
   763
                        REQ10400
sl@0
   764
*/
sl@0
   765
void AutoCompactionSizeTest()
sl@0
   766
	{
sl@0
   767
	DoCompactionDbSizeTest(EAutoSizeTest);
sl@0
   768
	}
sl@0
   769
sl@0
   770
/**
sl@0
   771
@SYMTestCaseID			SYSLIB-SQL-UT-4069
sl@0
   772
@SYMTestCaseDesc		Background compaction functional test.
sl@0
   773
						The test executes a 10 iterations loop with a "sleep" time 1000000 us at the beginning.
sl@0
   774
						The "sleep" time is divided by 2 on each iteration.
sl@0
   775
						In each iteration the test creates a database with free pages count big enough to kick-off the
sl@0
   776
						background compaction. Then the test executes enough Exec()s in order to kick-off the background compaction.
sl@0
   777
						Then the test "sleeps" the calculated "sleep" time and checks after that the database size and free pages
sl@0
   778
						count and prints them out. After the last iteration the same test is repeated with no "sleep" time.
sl@0
   779
						The test verifies how the client connection activity affects the possibility of the server to run the
sl@0
   780
						background compaction. 
sl@0
   781
@SYMTestPriority		Medium
sl@0
   782
@SYMTestActions			Background compaction functional test.
sl@0
   783
@SYMTestExpectedResults Test must not fail
sl@0
   784
@SYMREQ					REQ10271
sl@0
   785
                        REQ10407
sl@0
   786
*/
sl@0
   787
void BackgroundCompactionTest()
sl@0
   788
	{
sl@0
   789
	TInt interval = 1000000;//us
sl@0
   790
	const TInt KIterationCnt = 10;
sl@0
   791
	TheTest.Printf(_L("===Sleep after Exec()\r\n"));
sl@0
   792
	for(TInt i=0;i<KIterationCnt;++i)
sl@0
   793
		{
sl@0
   794
		(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   795
		CreateDatabase8(TheTestDbName);
sl@0
   796
		TInt err = TheDb.Open(TheTestDbName);
sl@0
   797
		TEST2(err, KErrNone);
sl@0
   798
		RSqlDatabase::TSize size1;
sl@0
   799
		err = TheDb.Size(size1);
sl@0
   800
		TEST2(err, KErrNone);
sl@0
   801
		TheTest.Printf(_L("---------------------------------\r\n"));
sl@0
   802
		TheTest.Printf(_L("===Sleep time %d ms. Database before background compaction: size %ld, free space %ld\r\n"), interval / 1000, size1.iSize, size1.iFree);
sl@0
   803
		//Simulate Exec() activities
sl@0
   804
		for(TInt j=0;j<100;++j)
sl@0
   805
			{
sl@0
   806
			err = TheDb.Exec(_L8("SELECT Id FROM A LIMIT 1"));
sl@0
   807
			TEST(err >= 0);
sl@0
   808
			}
sl@0
   809
		User::After(interval);
sl@0
   810
		RSqlDatabase::TSize size2;
sl@0
   811
		err = TheDb.Size(size2);
sl@0
   812
		TEST2(err, KErrNone);
sl@0
   813
		TheTest.Printf(_L("===Database after background compaction: size %ld, free space %ld\r\n"), size2.iSize, size2.iFree);
sl@0
   814
		TEST(size2.iSize <= size1.iSize);
sl@0
   815
		TEST(size2.iFree <= size1.iFree);
sl@0
   816
		interval /= 2;
sl@0
   817
		TheDb.Close();
sl@0
   818
		}
sl@0
   819
	TheTest.Printf(_L("===No sleep\r\n"));
sl@0
   820
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   821
	CreateDatabase8(TheTestDbName);
sl@0
   822
	TInt err = TheDb.Open(TheTestDbName);
sl@0
   823
	TEST2(err, KErrNone);
sl@0
   824
	RSqlDatabase::TSize size1;
sl@0
   825
	err = TheDb.Size(size1);
sl@0
   826
	TEST2(err, KErrNone);
sl@0
   827
	TheTest.Printf(_L("===Database before background compaction: size %ld, free space %ld\r\n"), size1.iSize, size1.iFree);
sl@0
   828
	//Simulate Exec() activities
sl@0
   829
	for(TInt j=0;j<100;++j)
sl@0
   830
		{
sl@0
   831
		err = TheDb.Exec(_L8("SELECT Id FROM A LIMIT 1"));
sl@0
   832
		TEST(err >= 0);
sl@0
   833
		}
sl@0
   834
	RSqlDatabase::TSize size2;
sl@0
   835
	err = TheDb.Size(size2);
sl@0
   836
	TEST2(err, KErrNone);
sl@0
   837
	TheTest.Printf(_L("===Database after background compaction: size %ld, free space %ld\r\n"), size2.iSize, size2.iFree);
sl@0
   838
	TEST(size2.iSize <= size1.iSize);
sl@0
   839
	TEST(size2.iFree <= size1.iFree);
sl@0
   840
	TheDb.Close();
sl@0
   841
	(void)RSqlDatabase::Delete(TheTestDbName);
sl@0
   842
	}
sl@0
   843
sl@0
   844
struct TThreadData
sl@0
   845
	{
sl@0
   846
	TThreadData(const TDesC& aFileName, TInt aSleepInterval) :
sl@0
   847
		iDbName(aFileName),
sl@0
   848
		iSleepInterval(aSleepInterval)
sl@0
   849
		{
sl@0
   850
		TInt err = iCritSection.CreateLocal();
sl@0
   851
		TEST2(err, KErrNone);
sl@0
   852
		iCritSection.Wait();
sl@0
   853
		Mem::FillZ(&iSize1, sizeof(iSize1));
sl@0
   854
		Mem::FillZ(&iSize2, sizeof(iSize2));
sl@0
   855
		}
sl@0
   856
	TFileName iDbName;	
sl@0
   857
	RCriticalSection iCritSection;
sl@0
   858
	RSqlDatabase::TSize iSize1;
sl@0
   859
	RSqlDatabase::TSize iSize2;
sl@0
   860
	TInt	iSleepInterval;
sl@0
   861
	};
sl@0
   862
sl@0
   863
TInt ThreadFunc(void* aPrm)
sl@0
   864
	{
sl@0
   865
	TEST(aPrm != NULL);
sl@0
   866
sl@0
   867
	__UHEAP_MARK;
sl@0
   868
	CTrapCleanup* tc = CTrapCleanup::New();
sl@0
   869
	TheTest(tc != NULL);
sl@0
   870
sl@0
   871
	//Wait for a signal from the main thread
sl@0
   872
	TThreadData* thrdat = (TThreadData*)aPrm;
sl@0
   873
	thrdat->iCritSection.Wait();
sl@0
   874
sl@0
   875
	RSqlDatabase db;
sl@0
   876
	TInt err = db.Open(thrdat->iDbName);
sl@0
   877
	TEST2(err, KErrNone);
sl@0
   878
	err = db.Size(thrdat->iSize1);
sl@0
   879
	TEST2(err, KErrNone);
sl@0
   880
	//Simulate Exec() activities
sl@0
   881
	for(TInt j=0;j<100;++j)
sl@0
   882
		{
sl@0
   883
		err = db.Exec(_L8("SELECT Id FROM A LIMIT 1"));
sl@0
   884
		TEST(err >= 0);
sl@0
   885
		if((j % 10) == 0 && thrdat->iSleepInterval > 0)
sl@0
   886
			{
sl@0
   887
			User::After(thrdat->iSleepInterval);
sl@0
   888
			}
sl@0
   889
		}
sl@0
   890
	err = db.Size(thrdat->iSize2);
sl@0
   891
	TEST2(err, KErrNone);
sl@0
   892
	db.Close();
sl@0
   893
sl@0
   894
	delete tc;	
sl@0
   895
	__UHEAP_MARKEND;
sl@0
   896
	return KErrNone;
sl@0
   897
	}
sl@0
   898
sl@0
   899
/**
sl@0
   900
@SYMTestCaseID			SYSLIB-SQL-UT-4070
sl@0
   901
@SYMTestCaseDesc		Background compaction load test.
sl@0
   902
						The test runs 8 threads. Each thread connects to a different database.
sl@0
   903
						Each database has space in the free pages above the "free pages" threshold - 
sl@0
   904
						the background compaction will be scheduled at the moment when the database is opened.
sl@0
   905
						Every thread executes some operations on the opened database - that will delay the background compaction.
sl@0
   906
						After every 10 operations the thread sleeps for a specified interval of a time.
sl@0
   907
						After all threads complete, the test checks the database size and free pages count and
sl@0
   908
						prints them out.
sl@0
   909
						The test verifies the ability of the SQL server to run the background compaction under a load.
sl@0
   910
@SYMTestPriority		Medium
sl@0
   911
@SYMTestActions			Background compaction load test.
sl@0
   912
@SYMTestExpectedResults Test must not fail
sl@0
   913
@SYMREQ					REQ10271
sl@0
   914
                        REQ10407
sl@0
   915
*/
sl@0
   916
void BackgroundCompactionLoadTest()
sl@0
   917
	{
sl@0
   918
	RThread threads[KMaxThreadCount];
sl@0
   919
	TThreadData* thrdata[KMaxThreadCount] = {NULL};
sl@0
   920
	TRequestStatus thrstat[KMaxThreadCount];
sl@0
   921
	
sl@0
   922
	const TInt KSleepInterval[] = {0, 50000, 100000, 300000, 500000, 800000};//us
sl@0
   923
	const TInt KTestCnt = sizeof(KSleepInterval) / sizeof(KSleepInterval[0]);
sl@0
   924
	
sl@0
   925
	for(TInt k=0;k<KTestCnt;++k)
sl@0
   926
		{
sl@0
   927
		TheTest.Printf(_L("=================================================\r\n"));
sl@0
   928
		TheTest.Printf(_L("===Sleep interval %d ms\r\n"), KSleepInterval[k] / 1000);
sl@0
   929
		TheTest.Printf(_L("=================================================\r\n"));
sl@0
   930
		//Create test databases and threads
sl@0
   931
		for(TInt i=0;i<TheTestThreadCount;++i)
sl@0
   932
			{
sl@0
   933
			//Database
sl@0
   934
			TBuf<16> fname;
sl@0
   935
			fname.Copy(_L("\\test\\a"));
sl@0
   936
			fname.AppendNum(i + 1);
sl@0
   937
			fname.Append(_L(".db"));
sl@0
   938
			TheParse.Set(TheDrive, &fname, 0);
sl@0
   939
			(void)RSqlDatabase::Delete(TheParse.FullName());
sl@0
   940
			CreateDatabase8(TheParse.FullName());
sl@0
   941
			//Thread data
sl@0
   942
			thrdata[i] = new TThreadData(TheParse.FullName(), KSleepInterval[k]);
sl@0
   943
			TEST(thrdata[i] != NULL);
sl@0
   944
			//Thread
sl@0
   945
			TBuf<16> thrname;
sl@0
   946
			thrname.Copy(_L("Thread"));
sl@0
   947
			thrname.AppendNum(i + 1);
sl@0
   948
			TInt err = threads[i].Create(thrname, &ThreadFunc, 0x2000, 0x1000, 0x10000, thrdata[i], EOwnerProcess);
sl@0
   949
			TEST2(err, KErrNone);
sl@0
   950
			threads[i].Logon(thrstat[i]);
sl@0
   951
			TEST2(thrstat[i].Int(), KRequestPending);
sl@0
   952
			threads[i].Resume();
sl@0
   953
			}
sl@0
   954
		//Enable the threads
sl@0
   955
		for(TInt i=0;i<TheTestThreadCount;++i)
sl@0
   956
			{
sl@0
   957
			thrdata[i]->iCritSection.Signal();	
sl@0
   958
			}
sl@0
   959
		//Wait for cmpletion
sl@0
   960
		for(TInt i=0;i<TheTestThreadCount;++i)
sl@0
   961
			{
sl@0
   962
			User::WaitForRequest(thrstat[i]);
sl@0
   963
			}
sl@0
   964
		//Report
sl@0
   965
		for(TInt i=0;i<TheTestThreadCount;++i)
sl@0
   966
			{
sl@0
   967
			TheTest.Printf(_L("===Thread %d, database %S\r\n"), i + 1, &(thrdata[i]->iDbName));
sl@0
   968
			TheTest.Printf(_L("===Before background compaction: size %6ld, free space %6ld\r\n"), thrdata[i]->iSize1.iSize, thrdata[i]->iSize1.iFree);
sl@0
   969
			TheTest.Printf(_L("===After background compaction:  size %6ld, free space %6ld\r\n"), thrdata[i]->iSize2.iSize, thrdata[i]->iSize2.iFree);
sl@0
   970
			TEST(thrdata[i]->iSize2.iSize <= thrdata[i]->iSize1.iSize);
sl@0
   971
			TEST(thrdata[i]->iSize2.iFree <= thrdata[i]->iSize1.iFree);
sl@0
   972
			}
sl@0
   973
		//Destroy
sl@0
   974
		for(TInt i=0;i<TheTestThreadCount;++i)
sl@0
   975
			{
sl@0
   976
			(void)RSqlDatabase::Delete(thrdata[i]->iDbName);
sl@0
   977
			thrdata[i]->iCritSection.Close();
sl@0
   978
			delete thrdata[i];
sl@0
   979
			thrdata[i] = NULL;
sl@0
   980
			CLOSE_AND_WAIT(threads[i]);
sl@0
   981
			}
sl@0
   982
		}
sl@0
   983
	}
sl@0
   984
sl@0
   985
/**
sl@0
   986
@SYMTestCaseID			SYSLIB-SQL-UT-4071
sl@0
   987
@SYMTestCaseDesc		Background compaction in a DDL transaction test.
sl@0
   988
						The test creates a database, begins a transaction that modifies the database structure  
sl@0
   989
						and executes enough operations in order free enough space to kick-off the background compaction. 
sl@0
   990
						The test should not report any failures caused by the fact that the main database connection is
sl@0
   991
						in a DML transaction and at the same time the background connection may try to execute
sl@0
   992
						a "PRAGMA freelist_count" statement.
sl@0
   993
@SYMTestPriority		Medium
sl@0
   994
@SYMTestActions			Background compaction in a DDL transaction test.
sl@0
   995
@SYMTestExpectedResults Test must not fail
sl@0
   996
@SYMREQ					REQ10271
sl@0
   997
*/
sl@0
   998
void BackgroundCompactionInDDLTransactionTest()
sl@0
   999
	{
sl@0
  1000
	const TInt KOperationCount = 100;
sl@0
  1001
	(void)RSqlDatabase::Delete(KDbName);
sl@0
  1002
	TInt err = TheDb.Create(KDbName);
sl@0
  1003
	TEST2(err, KErrNone);
sl@0
  1004
	err = TheDb.Exec(_L("BEGIN"));
sl@0
  1005
	TEST(err >= 0);
sl@0
  1006
	err = TheDb.Exec(_L("CREATE TABLE A(I INTEGER, T TEXT)"));
sl@0
  1007
	TEST2(err, 1);
sl@0
  1008
	TheText.SetLength(KTextLen);
sl@0
  1009
	TheText.Fill(TChar('A'));
sl@0
  1010
	for(TInt i=0;i<=KOperationCount;++i)	
sl@0
  1011
		{
sl@0
  1012
		TheSqlTexLen.Format(_L("INSERT INTO A VALUES(%d, '%S')"), i + 1, &TheText);
sl@0
  1013
		err = TheDb.Exec(TheSqlTexLen);
sl@0
  1014
		TEST2(err, 1);
sl@0
  1015
		}
sl@0
  1016
	err = TheDb.Exec(_L("COMMIT"));
sl@0
  1017
	TEST(err >= 0);
sl@0
  1018
	TheDb.Close();
sl@0
  1019
	(void)RSqlDatabase::Delete(KDbName);
sl@0
  1020
	}
sl@0
  1021
sl@0
  1022
/**
sl@0
  1023
@SYMTestCaseID			PDS-SQL-CT-4209
sl@0
  1024
@SYMTestCaseDesc		Corrupted database background compaction test.
sl@0
  1025
						The test creates a database, inserts records, then deletes part of the records.
sl@0
  1026
						The free pages count should be big enough to kick off the background compaction.
sl@0
  1027
						But the database is closed immediatelly and then the db file is corrupted in a such
sl@0
  1028
						way that during the "database open" operation the corruption is not detected.
sl@0
  1029
						But the corruption is detected during the background compaction. The SQL server
sl@0
  1030
						should detect during the compaction that the databas eis corrupted and should
sl@0
  1031
						stop compacting the database (and draining the battery). Unfortunatelly, this 
sl@0
  1032
						cannot be tested automatically, so a breakpoint should be set at the User::After()
sl@0
  1033
						call, and then the SQL server side should be debugged in order to berify that the
sl@0
  1034
						background compaction is really stopped for that database.  
sl@0
  1035
@SYMTestPriority		High
sl@0
  1036
@SYMTestActions			Corrupted database background compaction test.
sl@0
  1037
@SYMTestExpectedResults Test must not fail
sl@0
  1038
@SYMDEF					ou1cimx1#406830
sl@0
  1039
*/
sl@0
  1040
void CorruptedDbBckgCompactionTest()
sl@0
  1041
	{
sl@0
  1042
	//Step 1: Create a database with some records
sl@0
  1043
	const TInt KOperationCount = 100;
sl@0
  1044
	(void)RSqlDatabase::Delete(KDbName);
sl@0
  1045
	TInt err = TheDb.Create(KDbName);
sl@0
  1046
	TEST2(err, KErrNone);
sl@0
  1047
	err = TheDb.Exec(_L("BEGIN"));
sl@0
  1048
	TEST(err >= 0);
sl@0
  1049
	err = TheDb.Exec(_L("CREATE TABLE A(I INTEGER, T TEXT)"));
sl@0
  1050
	TEST2(err, 1);
sl@0
  1051
	TheText.SetLength(KTextLen);
sl@0
  1052
	TheText.Fill(TChar('A'));
sl@0
  1053
	for(TInt i=0;i<=KOperationCount;++i)	
sl@0
  1054
		{
sl@0
  1055
		TheSqlTexLen.Format(_L("INSERT INTO A VALUES(%d, '%S')"), i + 1, &TheText);
sl@0
  1056
		err = TheDb.Exec(TheSqlTexLen);
sl@0
  1057
		TEST2(err, 1);
sl@0
  1058
		}
sl@0
  1059
	err = TheDb.Exec(_L("COMMIT"));
sl@0
  1060
	TEST(err >= 0);
sl@0
  1061
	//Step 2: Delete some records to free some space
sl@0
  1062
	err = TheDb.Exec(_L("DELETE FROM A WHERE (I % 2) = 0"));
sl@0
  1063
	TEST(err > 0);
sl@0
  1064
	//Step 3: Close the database
sl@0
  1065
	TheDb.Close();
sl@0
  1066
	//Step 4: Corrupt the database
sl@0
  1067
    RFs fs;
sl@0
  1068
	err = fs.Connect();
sl@0
  1069
	TEST2(err, KErrNone);
sl@0
  1070
	RFile file;
sl@0
  1071
	err = file.Open(fs, KDbName, EFileRead | EFileWrite); 
sl@0
  1072
	TEST2(err, KErrNone);
sl@0
  1073
	TInt pos = 5000;
sl@0
  1074
	err = file.Seek(ESeekStart, pos);
sl@0
  1075
	TEST2(err, KErrNone);
sl@0
  1076
	TheSqlQuery.SetLength(1000);
sl@0
  1077
	for(TInt i=0;i<30;++i)
sl@0
  1078
		{
sl@0
  1079
		err = file.Write(TheSqlQuery);
sl@0
  1080
		TEST2(err, KErrNone);
sl@0
  1081
		}
sl@0
  1082
	file.Close();
sl@0
  1083
	//Step 5: Check the background compaction. Wait 10 seconds allowing the SQL server to try to compact the
sl@0
  1084
	//        database. The SQL server should detect that the SQL database is corrupted and should stop trying to
sl@0
  1085
	//        compact the database.
sl@0
  1086
	err = TheDb.Open(KDbName);
sl@0
  1087
	TEST2(err, KErrNone);
sl@0
  1088
	User::After(10000000);
sl@0
  1089
	//
sl@0
  1090
	TheDb.Close();
sl@0
  1091
	(void)RSqlDatabase::Delete(KDbName);
sl@0
  1092
	}
sl@0
  1093
sl@0
  1094
void DoTestsL()
sl@0
  1095
	{
sl@0
  1096
	CreateTestDatabase8();
sl@0
  1097
	CalculateMaxCompaction8();
sl@0
  1098
	CreateTestDatabase16();
sl@0
  1099
	CalculateMaxCompaction16();
sl@0
  1100
sl@0
  1101
	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4064 Manual Compact() - negative tests"));	
sl@0
  1102
	ManualCompactionNegativeTest();
sl@0
  1103
sl@0
  1104
	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4065 Manual Compact() tests"));	
sl@0
  1105
	ManualCompactionTest();
sl@0
  1106
sl@0
  1107
	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4066 Manual compaction db size test"));	
sl@0
  1108
	ManualCompactionSizeTest();
sl@0
  1109
sl@0
  1110
	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4068 Manual compaction - OOM test"));	
sl@0
  1111
	ManualCompactionOomTest();
sl@0
  1112
sl@0
  1113
	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4067 Auto compaction db size test"));	
sl@0
  1114
	AutoCompactionSizeTest();
sl@0
  1115
sl@0
  1116
	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4069 Background compaction test"));	
sl@0
  1117
	BackgroundCompactionTest();
sl@0
  1118
sl@0
  1119
	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4070 Background compaction - load test"));	
sl@0
  1120
	BackgroundCompactionLoadTest();
sl@0
  1121
sl@0
  1122
	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4071 Background compaction activated inside a DDL transaction - test"));	
sl@0
  1123
	BackgroundCompactionInDDLTransactionTest();
sl@0
  1124
	
sl@0
  1125
	TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-CT-4209 Corrupted database background compaction test"));	
sl@0
  1126
	CorruptedDbBckgCompactionTest();
sl@0
  1127
	}
sl@0
  1128
sl@0
  1129
TInt E32Main()
sl@0
  1130
	{
sl@0
  1131
	TheTest.Title();
sl@0
  1132
	
sl@0
  1133
	CTrapCleanup* tc = CTrapCleanup::New();
sl@0
  1134
	TheTest(tc != NULL);
sl@0
  1135
	
sl@0
  1136
	TheTest.Printf(_L("Usage:\r\n  t_sqlcompact4 [[drive:] [test thread count]]\r\n"));
sl@0
  1137
	TheDrive.Copy(KDefaultDriveName);
sl@0
  1138
	User::CommandLine(TheCmd);
sl@0
  1139
	TheCmd.TrimAll();
sl@0
  1140
	if(TheCmd.Length() > 0)
sl@0
  1141
		{
sl@0
  1142
		TInt pos = TheCmd.Locate(TChar(' '));
sl@0
  1143
		TheTest(pos > 0);
sl@0
  1144
		TPtrC prm1(TheCmd.Left(pos));
sl@0
  1145
		TPtrC prm2(TheCmd.Mid(pos + 1));
sl@0
  1146
		
sl@0
  1147
		TheDrive.Copy(prm1);
sl@0
  1148
		
sl@0
  1149
		TLex lex(prm2);
sl@0
  1150
		lex.Val(TheTestThreadCount);
sl@0
  1151
		}
sl@0
  1152
	TheParse.Set(TheDrive, &KDbName, 0);
sl@0
  1153
	TheTestDbName.Copy(TheParse.FullName());
sl@0
  1154
	TheTest.Printf(_L("Test database: %S\r\n"), &TheTestDbName);
sl@0
  1155
	
sl@0
  1156
	__UHEAP_MARK;
sl@0
  1157
	
sl@0
  1158
	CreateTestEnv();
sl@0
  1159
	TRAPD(err, DoTestsL());
sl@0
  1160
	DestroyTestEnv();
sl@0
  1161
	TEST2(err, KErrNone);
sl@0
  1162
	
sl@0
  1163
	__UHEAP_MARKEND;
sl@0
  1164
	
sl@0
  1165
	TheTest.End();
sl@0
  1166
	TheTest.Close();
sl@0
  1167
	
sl@0
  1168
	delete tc;
sl@0
  1169
	
sl@0
  1170
	User::Heap().Check();
sl@0
  1171
	return KErrNone;
sl@0
  1172
	}