persistentstorage/sql/TEST/t_sqlfserr.cpp
changeset 0 08ec8eefde2f
child 8 fa9941cf3867
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32test.h>
       
    17 #include <bautils.h>
       
    18 #include <sqldb.h>
       
    19 #include <stdio.h>
       
    20 #include <stdlib.h>
       
    21 #include <string.h> 
       
    22 #include "sqlite3.h"
       
    23 #include "SqliteSymbian.h"
       
    24 
       
    25 ///////////////////////////////////////////////////////////////////////////////////////
       
    26 
       
    27 RTest TheTest(_L("t_sqlfserr test"));
       
    28 _LIT(KTestDir, "c:\\test\\");
       
    29 _LIT(KTestDbName, "c:\\test\\t_fserr.db");
       
    30 TFileName TheRmvMediaDbFileName;//The name of the file used for tests on a removable media
       
    31 RFs TheFs;
       
    32 RSqlDatabase TheDb;
       
    33 
       
    34 //The next constants are used in the "blob write" test
       
    35 const TInt KWriteCnt = 9;
       
    36 const TInt KBlobSize = 397 * KWriteCnt;
       
    37 _LIT(KAttachDb, "AttachDb");
       
    38 
       
    39 //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)
       
    40 #ifdef _SQLPROFILER
       
    41 TInt TheSqlSrvProfilerFileRead = 0;
       
    42 TInt TheSqlSrvProfilerFileWrite = 0;
       
    43 TInt TheSqlSrvProfilerFileSync = 0;
       
    44 TInt TheSqlSrvProfilerFileSetSize = 0;
       
    45 #endif
       
    46 
       
    47 ///////////////////////////////////////////////////////////////////////////////////////
       
    48 
       
    49 TBool FileExists(const TDesC& aFileName)
       
    50 	{
       
    51 	TEntry entry;
       
    52 	return TheFs.Entry(aFileName, entry) == KErrNone;
       
    53 	}
       
    54 
       
    55 void DestroyTestEnv()
       
    56 	{
       
    57 	TheDb.Close();
       
    58 	(void)RSqlDatabase::Delete(KTestDbName);
       
    59 	(void)RSqlDatabase::Delete(TheRmvMediaDbFileName);
       
    60 	TheFs.Close();
       
    61 	sqlite3SymbianLibFinalize();
       
    62 	CloseSTDLIB();
       
    63 	}
       
    64 
       
    65 ///////////////////////////////////////////////////////////////////////////////////////
       
    66 ///////////////////////////////////////////////////////////////////////////////////////
       
    67 //Test macros and functions
       
    68 void Check(TInt aValue, TInt aLine)
       
    69 	{
       
    70 	if(!aValue)
       
    71 		{
       
    72 		DestroyTestEnv();
       
    73 		TheTest(EFalse, aLine);
       
    74 		}
       
    75 	}
       
    76 void Check(TInt aValue, TInt aExpected, TInt aLine)
       
    77 	{
       
    78 	if(aValue != aExpected)
       
    79 		{
       
    80 		DestroyTestEnv();
       
    81 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
       
    82 		TheTest(EFalse, aLine);
       
    83 		}
       
    84 	}
       
    85 #define TEST(arg) ::Check((arg), __LINE__)
       
    86 #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
       
    87 
       
    88 void SqliteCheck(sqlite3* aDbHandle, TInt aValue, TInt aExpected, TInt aLine)
       
    89 	{
       
    90 	if(aValue != aExpected)
       
    91 		{
       
    92 		RDebug::Print(_L("*** SQLITE: Expected error: %d, got: %d\r\n"), aExpected, aValue);
       
    93 		if(aDbHandle)
       
    94 			{
       
    95 			const char* errMsg = sqlite3_errmsg(aDbHandle);
       
    96 			TPtrC8 ptr8((const TUint8*)errMsg, strlen(errMsg));
       
    97 			TBuf<200> buf;
       
    98 			buf.Copy(ptr8);
       
    99 			RDebug::Print(_L("*** SQLITE error message: \"%S\"\r\n"), &buf);
       
   100 			}
       
   101 		DestroyTestEnv();
       
   102 		TheTest(EFalse, aLine);
       
   103 		}
       
   104 	}
       
   105 #define SQLITE_TEST(aDbHandle, aValue, aExpected) ::SqliteCheck(aDbHandle, aValue, aExpected, __LINE__)
       
   106 
       
   107 ///////////////////////////////////////////////////////////////////////////////////////
       
   108 
       
   109 void SetupTestEnv()
       
   110     {
       
   111 	TInt err = TheFs.Connect();
       
   112 	TEST2(err, KErrNone);
       
   113 
       
   114 	err = TheFs.MkDir(KTestDir);
       
   115 	TEST(err == KErrNone || err == KErrAlreadyExists);
       
   116 
       
   117 	sqlite3SymbianLibInit();
       
   118 	}
       
   119 
       
   120 TBool CheckRecord(TInt aId, const TDesC& aExpectedName, TBool aOpenDb = ETrue)
       
   121 	{
       
   122 	if(aOpenDb)
       
   123 		{
       
   124 		TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   125 		}
       
   126 	TBuf<64> sql;
       
   127 	sql.Copy(_L("SELECT Name FROM A WHERE Id="));
       
   128 	sql.AppendNum(aId);
       
   129 	TSqlScalarFullSelectQuery q(TheDb);
       
   130 	TBuf<20> name;
       
   131 	TRAPD(err, (void)q.SelectTextL(sql, name));
       
   132 	TEST2(err, KErrNone);
       
   133 	if(aOpenDb)
       
   134 		{
       
   135 		TheDb.Close();
       
   136 		}
       
   137 	return name == aExpectedName;
       
   138 	}
       
   139 
       
   140 ///////////////////////////////////////////////////////////////////////////////////////
       
   141 
       
   142 /**
       
   143 @SYMTestCaseID			SYSLIB-SQL-UT-3419
       
   144 @SYMTestCaseDesc		Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
       
   145 						The test creates a test database with one table, inserts one record.
       
   146 						Then the test attempts to update the existing record while simulating file I/O failures.
       
   147 						After each test iteration the database content is tested and is expected to be the same
       
   148 						as it was before the test. RSqlDatabase::Exec() is used for the update operation.
       
   149 @SYMTestPriority		High
       
   150 @SYMTestActions			Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
       
   151 @SYMTestExpectedResults The test must not fail
       
   152 @SYMDEF					DEF103859
       
   153 */
       
   154 void AlterDatabaseTest()
       
   155 	{
       
   156 	(void)RSqlDatabase::Delete(KTestDbName);
       
   157 	TInt err = TheDb.Create(KTestDbName);
       
   158 	TEST2(err, KErrNone);
       
   159 	err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT)"));
       
   160 	TEST(err >= 0);
       
   161 	TheDb.Close();
       
   162 	err = KErrNotFound;
       
   163 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   164 		{
       
   165 		TheTest.Printf(_L("%d \r"), cnt);		
       
   166 		for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
       
   167 			{
       
   168 			//Preprocessing
       
   169 			TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   170 			(void)TheDb.Exec(_L("DELETE FROM A WHERE Id=1"));
       
   171 			err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
       
   172 			TEST2(err, 1);
       
   173 			//The test
       
   174 			(void)TheFs.SetErrorCondition(fsError, cnt);
       
   175 			err = TheDb.Exec(_L("UPDATE A SET Name='Name2' WHERE Id=1"));
       
   176 			(void)TheFs.SetErrorCondition(KErrNone);
       
   177 			if(err < 1)
       
   178 				{
       
   179 				TheDb.Close();//close the database to recover from the last error
       
   180 				//check the database content - all bets are off in a case of an I/O error. 
       
   181 				//The existing record might have been updated.
       
   182 				TEST(CheckRecord(1, _L("Name")) || CheckRecord(1, _L("Name2")));
       
   183 				}
       
   184 			else
       
   185 				{
       
   186 				TEST2(err, 1);
       
   187 				//check the database content has been modified by the operation. 
       
   188 				TEST(CheckRecord(1, _L("Name2"), EFalse));
       
   189 				TheDb.Close();
       
   190 				}
       
   191 			}
       
   192 		}
       
   193 	(void)TheFs.SetErrorCondition(KErrNone);
       
   194 	TEST2(err, 1);
       
   195 	//check the database content (transaction durability). 
       
   196 	TEST(CheckRecord(1, _L("Name2")));
       
   197 	err = RSqlDatabase::Delete(KTestDbName);
       
   198 	TEST2(err, KErrNone);
       
   199 	TheTest.Printf(_L("\r\n"));
       
   200 	}
       
   201 
       
   202 /**
       
   203 @SYMTestCaseID			SYSLIB-SQL-UT-3420
       
   204 @SYMTestCaseDesc		Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
       
   205 						The test creates a test database with one table, inserts one record.
       
   206 						Then the test attempts to update the existing record while simulating file I/O failures.
       
   207 						After each test iteration the database content is tested and is expected to be the same
       
   208 						as it was before the test. RSqlStatement::Exec() is used for the update operation.
       
   209 @SYMTestPriority		High
       
   210 @SYMTestActions			Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
       
   211 @SYMTestExpectedResults The test must not fail
       
   212 @SYMDEF					DEF103859
       
   213 */
       
   214 void AlterDatabaseTest2()
       
   215 	{
       
   216 	(void)RSqlDatabase::Delete(KTestDbName);
       
   217 	TInt err = TheDb.Create(KTestDbName);
       
   218 	TEST2(err, KErrNone);
       
   219 	err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT)"));
       
   220 	TEST(err >= 0);
       
   221 	TheDb.Close();
       
   222 	err = KErrNotFound;
       
   223 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   224 		{
       
   225 		TheTest.Printf(_L("%d \r"), cnt);		
       
   226 		for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
       
   227 			{
       
   228 			//Preprocessing
       
   229 			TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   230 			(void)TheDb.Exec(_L("DELETE FROM A WHERE Id=1"));
       
   231 			err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
       
   232 			TEST2(err, 1);
       
   233 			//The test
       
   234 			(void)TheFs.SetErrorCondition(fsError, cnt);
       
   235 			RSqlStatement stmt;
       
   236 			err = stmt.Prepare(TheDb, _L("UPDATE A SET Name='Name2' WHERE Id=1"));
       
   237 			if(err == KErrNone)
       
   238 				{
       
   239 				err = stmt.Exec();	
       
   240 				}
       
   241 			(void)TheFs.SetErrorCondition(KErrNone);
       
   242 			stmt.Close();
       
   243 			if(err < 1)
       
   244 				{
       
   245 				TheDb.Close();//close the database to recover from the last error
       
   246 				//check the database content - all bets are off in a case of an I/O error. 
       
   247 				//The existing record might have been updated.
       
   248 				TEST(CheckRecord(1, _L("Name")) || CheckRecord(1, _L("Name2")));
       
   249 				}
       
   250 			else
       
   251 				{
       
   252 				TEST2(err, 1);
       
   253 				//check the database content has been modified by the operation. 
       
   254 				TEST(CheckRecord(1, _L("Name2"), EFalse));
       
   255 				TheDb.Close();
       
   256 				}
       
   257 			}
       
   258 		}
       
   259 	(void)TheFs.SetErrorCondition(KErrNone);
       
   260 	TEST2(err, 1);
       
   261 	//check the database content has been modified by the operation. 
       
   262 	TEST(CheckRecord(1, _L("Name2")));
       
   263 	err = RSqlDatabase::Delete(KTestDbName);
       
   264 	TEST2(err, KErrNone);
       
   265 	TheTest.Printf(_L("\r\n"));
       
   266 	}
       
   267 
       
   268 /**
       
   269 @SYMTestCaseID			SYSLIB-SQL-UT-3421
       
   270 @SYMTestCaseDesc		Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
       
   271 						The test creates a test database with one table, inserts one record.
       
   272 						Then the test attempts to open the database while simulating file I/O failures.
       
   273 						At the end of the test the database content is tested and is expected to be the same
       
   274 						as it was before the test. RSqlStatement::Open() is used in the test.
       
   275 @SYMTestPriority		High
       
   276 @SYMTestActions			Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
       
   277 @SYMTestExpectedResults The test must not fail
       
   278 @SYMDEF					DEF103859
       
   279 */
       
   280 void OpenDatabaseTest()
       
   281 	{
       
   282 	(void)RSqlDatabase::Delete(KTestDbName);
       
   283 	TInt err = TheDb.Create(KTestDbName);
       
   284 	TEST2(err, KErrNone);
       
   285 	err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT)"));
       
   286 	TEST(err >= 0);
       
   287 	err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
       
   288 	TEST2(err, 1);
       
   289 	TheDb.Close();
       
   290 
       
   291 	err = KErrNotFound;
       
   292 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   293 		{		
       
   294 		TheTest.Printf(_L("%d \r"), cnt);		
       
   295 		for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
       
   296 			{
       
   297 			(void)TheFs.SetErrorCondition(fsError, cnt);
       
   298 			err = TheDb.Open(KTestDbName);
       
   299 			(void)TheFs.SetErrorCondition(KErrNone);
       
   300 			if(err != KErrNone)
       
   301 				{
       
   302 				TheDb.Close();//close the database to recover from the last error
       
   303 				//check the database content is still the same as before the "open" call
       
   304 				TEST(CheckRecord(1, _L("Name")));
       
   305 				}
       
   306 			else
       
   307 				{
       
   308 				TEST2(err, KErrNone);
       
   309 				//check the database content is still the same as before the operation, without closing the database
       
   310 				TEST(CheckRecord(1, _L("Name"), EFalse));
       
   311 				TheDb.Close();
       
   312 				}
       
   313 			}
       
   314 		}
       
   315 	(void)TheFs.SetErrorCondition(KErrNone);
       
   316 	TEST2(err, KErrNone);
       
   317 	//check the database content is the same as before the operation, after reopening the database.
       
   318 	TEST(CheckRecord(1, _L("Name")));
       
   319 	err = RSqlDatabase::Delete(KTestDbName);
       
   320 	TEST2(err, KErrNone);
       
   321 	TheTest.Printf(_L("\r\n"));
       
   322 	}
       
   323 
       
   324 /**
       
   325 @SYMTestCaseID			SYSLIB-SQL-UT-3434
       
   326 @SYMTestCaseDesc		Test for DEF104820 "SQL, RSqlDatabase::Create() does not delete the file if fails".
       
   327 						Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
       
   328 						Then the test attempts to create a database while simulating file I/O failures.
       
   329 						When the test succeeds, the test verifies that the database file does exist.
       
   330 @SYMTestPriority		High
       
   331 @SYMTestActions			Test for DEF104820 "SQL, RSqlDatabase::Create() does not delete the file if fails".
       
   332 						Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
       
   333 @SYMTestExpectedResults The test must not fail
       
   334 @SYMDEF					DEF103859
       
   335 */
       
   336 void CreateDatabaseTest()
       
   337 	{
       
   338 	TInt err = -1;
       
   339 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   340 		{		
       
   341 		TheTest.Printf(_L("%d \r"), cnt);		
       
   342 		for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
       
   343 			{
       
   344 			//Ideally, the database should be deleted by the SQL server, if RSqlDatabase::Create() fails.
       
   345 			//But SetErrorCondition() makes the error persistent, so the SQL server will fail to delete the file.
       
   346 			//This is the reason, RSqlDatabase::Delete()to be used, before simulating file I/O error.
       
   347 			(void)RSqlDatabase::Delete(KTestDbName);
       
   348 			(void)TheFs.SetErrorCondition(fsError, cnt);
       
   349 			err = TheDb.Create(KTestDbName);
       
   350 			(void)TheFs.SetErrorCondition(KErrNone);
       
   351 			TheDb.Close();
       
   352 			//If err != KErrNone, the database file should have been already deleted by the server and here is 
       
   353 			//the place to check that. But since the file I/O failure simulation makes the file I/O error 
       
   354 			//persistent, the file cannot be deleted by the server, because the "file delete" operation also fails.
       
   355 			}
       
   356 		}
       
   357 	(void)TheFs.SetErrorCondition(KErrNone);
       
   358 	TheDb.Close();
       
   359 	TEST2(err, KErrNone);
       
   360 	TEST(FileExists(KTestDbName));
       
   361 	err = RSqlDatabase::Delete(KTestDbName);
       
   362 	TEST2(err, KErrNone);
       
   363 	TheTest.Printf(_L("\r\n"));
       
   364 	}
       
   365 
       
   366 /**
       
   367 @SYMTestCaseID			SYSLIB-SQL-UT-3462
       
   368 @SYMTestCaseDesc		Test for DEF105434 "SQL, persistent file I/O simulation, COMMIT problem".
       
   369 						The test creates a test database with one table, inserts one record.
       
   370 						Then the test attempts to retrieve the existing record while simulating file I/O failures.
       
   371 						After each iteration, the database content is tested, that it has not been modified by the operation.
       
   372 @SYMTestPriority		High
       
   373 @SYMTestActions			Test for DEF105434 "SQL, persistent file I/O simulation, COMMIT problem".
       
   374 @SYMTestExpectedResults The test must not fail
       
   375 @SYMDEF					DEF105434
       
   376 */
       
   377 void SelectRecordTest()
       
   378 	{
       
   379 	(void)RSqlDatabase::Delete(KTestDbName);
       
   380 	TInt err = TheDb.Create(KTestDbName);
       
   381 	TEST2(err, KErrNone);
       
   382 	err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER, Name TEXT)"));
       
   383 	TEST(err >= 0);
       
   384 	err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
       
   385 	TEST2(err, 1);
       
   386 	TheDb.Close();
       
   387 	err = -1;
       
   388 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   389 		{		
       
   390 		TheTest.Printf(_L("%d \r"), cnt);		
       
   391 		err = TheDb.Open(KTestDbName);
       
   392 		TEST2(err, KErrNone);
       
   393 		RSqlStatement stmt;
       
   394 		(void)TheFs.SetErrorCondition(KErrGeneral, cnt);
       
   395 		err = stmt.Prepare(TheDb, _L("SELECT * FROM A WHERE Id=?"));
       
   396 		if(err == KErrNone)
       
   397 			{
       
   398 			err = stmt.BindInt(0, 1);
       
   399 			if(err == KErrNone)
       
   400 				{
       
   401 				err = stmt.Next();
       
   402 				TEST(err == KSqlAtRow || err < 0);
       
   403 				if(err == KSqlAtRow)
       
   404 					{
       
   405 					TInt id = stmt.ColumnInt(0);
       
   406 					TEST2(id, 1);
       
   407 					TPtrC name;
       
   408 					err = stmt.ColumnText(1, name);
       
   409 					TEST2(err, KErrNone);
       
   410 					TEST(name == _L("Name"));
       
   411 					}
       
   412 				}
       
   413 			}
       
   414 		(void)TheFs.SetErrorCondition(KErrNone);
       
   415 		stmt.Close();
       
   416 		TheDb.Close();
       
   417 		//check the database content is the same as before the operation
       
   418 		TEST(CheckRecord(1, _L("Name")));
       
   419 		}
       
   420 	(void)TheFs.SetErrorCondition(KErrNone);
       
   421 	TEST(err >= 0);
       
   422 	TheDb.Close();
       
   423 	//check the database content is the same as before the operation, after reopening the database.
       
   424 	TEST(CheckRecord(1, _L("Name")));
       
   425 	err = RSqlDatabase::Delete(KTestDbName);
       
   426 	TEST2(err, KErrNone);
       
   427 	TheTest.Printf(_L("\r\n"));
       
   428 	}
       
   429 
       
   430 /**
       
   431 @SYMTestCaseID			SYSLIB-SQL-UT-3463
       
   432 @SYMTestCaseDesc		Test for DEF105434 "SQL, persistent file I/O simulation, COMMIT problem".
       
   433 						The test creates a test database with one table, inserts one record.
       
   434 						Then the test attempts to insert another while simulating file I/O failures.
       
   435 						After each iteration, the database content is tested, that it has not been modified by the operation.
       
   436 						If the operation succeeds, the database content is tested again to check that the inserted record is there.
       
   437 @SYMTestPriority		High
       
   438 @SYMTestActions			Test for DEF105434 "SQL, persistent file I/O simulation, COMMIT problem".
       
   439 @SYMTestExpectedResults The test must not fail
       
   440 @SYMDEF					DEF105434
       
   441 */
       
   442 void InsertRecordTest()
       
   443 	{
       
   444 	(void)RSqlDatabase::Delete(KTestDbName);
       
   445 	TInt err = TheDb.Create(KTestDbName);
       
   446 	TEST2(err, KErrNone);
       
   447 	err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT)"));
       
   448 	TEST(err >= 0);
       
   449 	err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
       
   450 	TEST2(err, 1);
       
   451 	TheDb.Close();
       
   452 	err = -1;
       
   453 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   454 		{		
       
   455 		TheTest.Printf(_L("%d \r"), cnt);		
       
   456 		err = TheDb.Open(KTestDbName);
       
   457 		TEST2(err, KErrNone);
       
   458 		RSqlStatement stmt;
       
   459 		(void)TheFs.SetErrorCondition(KErrGeneral, cnt);
       
   460 		err = stmt.Prepare(TheDb, _L("INSERT INTO A(Id,Name) VALUES(2, 'Name2')"));
       
   461 		if(err == KErrNone)
       
   462 			{
       
   463 			err = TheDb.Exec(_L("BEGIN TRANSACTION"));
       
   464 			if(err == KErrNone)
       
   465 				{
       
   466 				err = stmt.Exec();
       
   467 				TEST(err == 1 || err < 0);
       
   468 				if(err == 1)
       
   469 					{
       
   470 					err = TheDb.Exec(_L("COMMIT TRANSACTION"));
       
   471 					}
       
   472 				}
       
   473 			}
       
   474 		(void)TheFs.SetErrorCondition(KErrNone);
       
   475 		stmt.Close();
       
   476 		if(err < 1)
       
   477 			{
       
   478 			TheDb.Close();//close the database to recover from the last error
       
   479 			//check that the database contains the "name" record that has been inserted before the file I/O failure test.
       
   480 			TEST(CheckRecord(1, _L("Name")));
       
   481 			}
       
   482 		else
       
   483 			{
       
   484 			TEST2(err, 1);
       
   485 			//check the database content has been modified by the operation, without closing the database.
       
   486 			TEST(CheckRecord(1, _L("Name"), EFalse));
       
   487 			TEST(CheckRecord(2, _L("Name2"), EFalse));
       
   488 			TheDb.Close();
       
   489 			}
       
   490 		}
       
   491 	(void)TheFs.SetErrorCondition(KErrNone);
       
   492 	TEST2(err, 1);
       
   493 	//check the database content (transaction durability).
       
   494 	TEST(CheckRecord(1, _L("Name")));
       
   495 	TEST(CheckRecord(2, _L("Name2")));
       
   496 	(void)RSqlDatabase::Delete(KTestDbName);
       
   497 	TheTest.Printf(_L("\r\n"));
       
   498 	}
       
   499 
       
   500 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   501 //////////////////////////////////         Removable media robustness test      /////////////////////////////////////////
       
   502 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   503 
       
   504 _LIT8(KNameColData, "A123456789012345678901234567890");
       
   505 _LIT8(KUpdatedNameColData, "1234");
       
   506 
       
   507 //TRemovableMediaTest class is used for testing the SQLITE behaviour when the database file is created on a removable media where
       
   508 //the cluster size is bigger than the page size and in case of a power failure is not guaranteed that the content
       
   509 //of the last updated cluster will be preserved.
       
   510 class TRemovableMediaTest
       
   511 	{
       
   512 	enum {KTestRecCnt = 200};
       
   513 	enum {KMinCachePageSize = 512};
       
   514 	
       
   515 public:	
       
   516 	void Run();
       
   517 	
       
   518 private:	
       
   519 	TInt GetRemovableMediaDriveNo();
       
   520 	TInt ClusterSize(TInt aDriveNo);
       
   521 	void CreateDatabase(TInt aDriveNo, TInt aCachePageSize);
       
   522 	void CheckRecord(sqlite3_stmt* aStmt, TInt aRecId);
       
   523 	void VerifyDatabase();
       
   524 	void DoTest();
       
   525 
       
   526 	};
       
   527 
       
   528 //Returns the number of the removable media drive, KErrNotFound otherwise.
       
   529 TInt TRemovableMediaTest::GetRemovableMediaDriveNo()
       
   530 	{
       
   531 	for(TInt driveNo=EDriveA;driveNo<=EDriveZ;++driveNo)
       
   532 		{
       
   533 		TDriveInfo driveInfo;
       
   534 		TInt err = TheFs.Drive(driveInfo, driveNo);
       
   535 		if(err == KErrNone)
       
   536 			{
       
   537 			_LIT(KType1, "Not present");
       
   538 			_LIT(KType2, "Unknown");
       
   539 			_LIT(KType3, "Floppy");
       
   540 			_LIT(KType4, "Hard disk");
       
   541 			_LIT(KType5, "CD ROM");
       
   542 			_LIT(KType6, "RAM disk");
       
   543 			_LIT(KType7, "Flash");
       
   544 			_LIT(KType8, "ROM drive");
       
   545 			_LIT(KType9, "Remote drive");
       
   546 			_LIT(KType10,"NAND flash");
       
   547 			_LIT(KType11,"Rotating media");
       
   548 			_LIT(KYes, "Yes");
       
   549 			_LIT(KNo,  "No ");
       
   550 			TPtrC KMediaTypeNames[] = {KType1(), KType2(), KType3(), KType4(), KType5(), KType6(), KType7(), KType8(), KType9(), KType10(), KType11()};
       
   551 			TheTest.Printf(_L("Drive: %C:, %S, Removable: %S\r\n"), 'A' + driveNo, &KMediaTypeNames[driveInfo.iType], 
       
   552 																	driveInfo.iDriveAtt & KDriveAttRemovable ? &KYes : &KNo);
       
   553 			if(driveInfo.iDriveAtt & KDriveAttRemovable)
       
   554 				{
       
   555 				TheTest.Printf(_L("Removable drive to test: %C:\r\n"), 'A' + driveNo);
       
   556 				return driveNo;	
       
   557 				}
       
   558 			}
       
   559 		}
       
   560 	return KErrNotFound;
       
   561 	}
       
   562 
       
   563 //Get the cluster size of aDriveNo drive	
       
   564 TInt TRemovableMediaTest::ClusterSize(TInt aDriveNo)
       
   565 	{
       
   566 	__ASSERT_DEBUG((TUint)aDriveNo <= EDriveZ, User::Invariant());
       
   567 	TVolumeIOParamInfo volIoParams;
       
   568 	TInt err = TheFs.VolumeIOParam(aDriveNo, volIoParams);
       
   569 	return (err == KErrNone) ? volIoParams.iClusterSize : err;
       
   570 	}
       
   571 
       
   572 //Create a test database on aDriveNo with aCachePageSize page size.
       
   573 //Insert KTestRecCnt records.
       
   574 void TRemovableMediaTest::CreateDatabase(TInt aDriveNo, TInt aCachePageSize)
       
   575 	{
       
   576 	__ASSERT_DEBUG((TUint)aDriveNo <= EDriveZ, User::Invariant());
       
   577 	__ASSERT_DEBUG(aCachePageSize > 0, User::Invariant());
       
   578 	TDriveUnit drvUnit(aDriveNo);
       
   579 	_LIT(KDbName, "\\flashmedia.db");
       
   580 	TParse parse;
       
   581 	parse.Set(drvUnit.Name(), &KDbName, 0);
       
   582 	TheRmvMediaDbFileName.Copy(parse.FullName());
       
   583 	TBuf8<KMaxFileName + 1> dbFileName8;
       
   584 	dbFileName8.Copy(TheRmvMediaDbFileName);
       
   585 	(void)TheFs.Delete(TheRmvMediaDbFileName);
       
   586 	
       
   587 	sqlite3* dbHandle = NULL;
       
   588 	TInt rc = sqlite3_open((const char*)dbFileName8.PtrZ(), &dbHandle);
       
   589 	SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   590 	__ASSERT_DEBUG(dbHandle != NULL, User::Invariant());
       
   591 	
       
   592 	TBuf8<40> config;
       
   593 	config.Copy(_L8("PRAGMA PAGE_SIZE="));
       
   594 	config.AppendNum(aCachePageSize);
       
   595 	rc = sqlite3_exec(dbHandle, (const char*)config.PtrZ(), 0, 0, 0);
       
   596 	SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   597 
       
   598 	rc = sqlite3_exec(dbHandle, "CREATE TABLE A(Id INTEGER,Name TEXT)", 0, 0, 0);
       
   599 	SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   600 	rc = sqlite3_exec(dbHandle, "BEGIN", 0, 0, 0);
       
   601 	SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   602 	for(TInt recid=1;recid<=KTestRecCnt;++recid)
       
   603 		{
       
   604 		
       
   605 		TBuf8<100> sql;
       
   606 		sql.Copy(_L8("INSERT INTO A VALUES("));
       
   607 		sql.AppendNum(recid);
       
   608 		sql.Append(_L8(",'"));
       
   609 		sql.Append(KNameColData);
       
   610 		sql.Append(_L8("')"));
       
   611 		rc = sqlite3_exec(dbHandle, (const char*)sql.PtrZ(), 0, 0, 0);
       
   612 		SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   613 		}
       
   614 	rc = sqlite3_exec(dbHandle, "COMMIT", 0, 0, 0);
       
   615 	SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   616 	sqlite3_close(dbHandle);
       
   617 	}
       
   618 
       
   619 //Checks the content of a single record
       
   620 void TRemovableMediaTest::CheckRecord(sqlite3_stmt* aStmt, TInt aRecId)
       
   621 	{
       
   622 	__ASSERT_DEBUG(aStmt != NULL, User::Invariant());
       
   623 	TInt id = sqlite3_column_int(aStmt, 0);
       
   624 	TEST2(id, aRecId);
       
   625 	const TUint8* text = (const TUint8*)sqlite3_column_text(aStmt, 1);
       
   626 	TPtrC8 name(text, User::StringLength(text));
       
   627 	TEST(KNameColData() == name || KUpdatedNameColData() == name);
       
   628 	}
       
   629 
       
   630 //Verifies that the database content is either the same as it was before the UPDATE operation or 
       
   631 //it has been updated with the new data.
       
   632 void TRemovableMediaTest::VerifyDatabase()
       
   633 	{
       
   634 	TBuf8<KMaxFileName + 1> dbFileName8;
       
   635 	dbFileName8.Copy(TheRmvMediaDbFileName);
       
   636 	
       
   637 	sqlite3* dbHandle = NULL;
       
   638 	TInt rc = sqlite3_open((const char*)dbFileName8.PtrZ(), &dbHandle);
       
   639 	SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   640 	__ASSERT_DEBUG(dbHandle != NULL, User::Invariant());
       
   641 	
       
   642 	sqlite3_stmt* stmtHandle = NULL;
       
   643 	rc = sqlite3_prepare(dbHandle, "SELECT Id,Name FROM A", -1, &stmtHandle, 0);
       
   644 	SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   645 	__ASSERT_DEBUG(stmtHandle != NULL, User::Invariant());
       
   646 	
       
   647 	for(TInt recid=1;recid<=KTestRecCnt;++recid)
       
   648 		{
       
   649 		rc = sqlite3_step(stmtHandle);
       
   650 		SQLITE_TEST(dbHandle, rc, SQLITE_ROW);
       
   651 		CheckRecord(stmtHandle, recid);
       
   652 		}
       
   653 	rc = sqlite3_step(stmtHandle);
       
   654 	SQLITE_TEST(dbHandle, rc, SQLITE_DONE);
       
   655 	
       
   656 	sqlite3_finalize(stmtHandle);
       
   657 	sqlite3_close(dbHandle);
       
   658 	}
       
   659 
       
   660 //Simulates a file system error in a loop.
       
   661 //Attempts to update single record in a transaction.
       
   662 //If the UPDATE operation fails - verifies the database content on each iteration.
       
   663 //Note: pages are stored at the moment, not clusters. The database operations are not more robust if
       
   664 //      clusters are stored in a case of a removable media.
       
   665 void TRemovableMediaTest::DoTest()
       
   666 	{
       
   667 	TheTest.Printf(_L("Update 1 record in a file I/o simulation loop\r\n"));		
       
   668 	TInt rc = -1;
       
   669 	TBuf8<KMaxFileName + 1> dbFileName8;
       
   670 	dbFileName8.Copy(TheRmvMediaDbFileName);
       
   671 	for(TInt cnt=1;rc!=SQLITE_OK;++cnt)
       
   672 		{		
       
   673 		TheTest.Printf(_L("%d \r"), cnt);		
       
   674 		sqlite3* dbHandle = NULL;
       
   675 		rc = sqlite3_open((const char*)dbFileName8.PtrZ(), &dbHandle);
       
   676 		SQLITE_TEST(dbHandle, rc, SQLITE_OK);
       
   677 		__ASSERT_DEBUG(dbHandle != NULL, User::Invariant());
       
   678 		(void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
       
   679 		rc = sqlite3_exec(dbHandle, "BEGIN IMMEDIATE", 0, 0, 0);
       
   680 		if(rc == SQLITE_OK)
       
   681 			{
       
   682 			rc = sqlite3_exec(dbHandle, "UPDATE A SET Name='1234' WHERE Id=1", 0, 0, 0);
       
   683 			if(rc == SQLITE_OK)
       
   684 				{
       
   685 				TInt cnt = sqlite3_changes(dbHandle);
       
   686 				TEST2(cnt, 1);
       
   687 				rc = sqlite3_exec(dbHandle, "COMMIT", 0, 0, 0);
       
   688 				}
       
   689 			}
       
   690 		(void)TheFs.SetErrorCondition(KErrNone);
       
   691 		sqlite3_close(dbHandle);
       
   692 		if(rc != SQLITE_OK)
       
   693 			{
       
   694 			VerifyDatabase();
       
   695 			}
       
   696 		}
       
   697 	TEST2(rc, SQLITE_OK);
       
   698 	VerifyDatabase();
       
   699 	}
       
   700 	
       
   701 void TRemovableMediaTest::Run()
       
   702 	{
       
   703 	TInt driveNo = GetRemovableMediaDriveNo();
       
   704 	if(driveNo == KErrNotFound)
       
   705 		{
       
   706 		TheTest.Printf(_L("No removable media discovered. Test case not executed.\r\n"));	
       
   707 		return;
       
   708 		}
       
   709 	TInt clusterSize = ClusterSize(driveNo);
       
   710 	if(clusterSize < 0)
       
   711 		{
       
   712 		TheTest.Printf(_L("Error %d retrieving the cluster size of drive %C. Test case not executed.\r\n"), clusterSize, 'A' + driveNo);
       
   713 		return;
       
   714 		}
       
   715 	if(clusterSize <= KMinCachePageSize)
       
   716 		{
       
   717 		TheTest.Printf(_L("Cluster size: %d. No appropriate cache page size found. Test case not executed.\r\n"), clusterSize);	
       
   718 		return;
       
   719 		}
       
   720 		
       
   721 	TheTest.Printf(_L("Cluster size: %d. Cache page size %d.\r\nBegin test.\r\n"), clusterSize, KMinCachePageSize);	
       
   722 	CreateDatabase(driveNo, KMinCachePageSize);
       
   723 	DoTest();
       
   724 	(void)TheFs.Delete(TheRmvMediaDbFileName);
       
   725 	TheTest.Printf(_L("End test.\r\n"));
       
   726 	}
       
   727 
       
   728 /**
       
   729 @SYMTestCaseID			SYSLIB-SQL-UT-3516
       
   730 @SYMTestCaseDesc		Removable media robustness test
       
   731 						The test creates a test database with a table with some records. Then the test verifies
       
   732 						that the database content cannot be corrupted by file I/O failures during database updates, 
       
   733 						when the database file is on a removable media and the media cluster size is bigger than the 
       
   734 						database page size.
       
   735 @SYMTestPriority		High
       
   736 @SYMTestActions			Removable media robustness test
       
   737 @SYMTestExpectedResults The test must not fail
       
   738 @SYMREQ					REQ7913
       
   739 */
       
   740 void RemovableMediaRobustnessTest()
       
   741 	{
       
   742 	TRemovableMediaTest removableMediaTest;
       
   743 	removableMediaTest.Run();
       
   744 	}
       
   745 
       
   746 /**
       
   747 @SYMTestCaseID			SYSLIB-SQL-UT-4044
       
   748 @SYMTestCaseDesc		RSqlDatabase::Size(TSize&), file I/O error simulation test.
       
   749 						The test creates a database and executes RSqldatabase::Size(TSize&)
       
   750 						during a file I/O error simulation. The database should not be corrupted 
       
   751 						by the call.
       
   752 @SYMTestPriority		High
       
   753 @SYMTestActions			RSqlDatabase::Size(TSize&), file I/O error simulation test.
       
   754 @SYMTestExpectedResults Test must not fail
       
   755 @SYMREQ					REQ10407
       
   756 */
       
   757 void SizeTest()
       
   758 	{
       
   759 	(void)RSqlDatabase::Delete(KTestDbName);
       
   760 	TInt err = TheDb.Create(KTestDbName);
       
   761 	TEST2(err, KErrNone);
       
   762 	err = TheDb.Exec(_L("BEGIN;CREATE TABLE A(Id INTEGER,Data BLOB);INSERT INTO A VALUES(1, x'11223344');COMMIT;"));
       
   763 	TEST(err >= 0);
       
   764 	RSqlDatabase::TSize size1 = {-1, -1};
       
   765 	err = TheDb.Size(size1);
       
   766 	TEST2(err, KErrNone);
       
   767 	TEST(size1.iSize > 0);
       
   768 	TEST2(size1.iFree, 0);
       
   769 	TheDb.Close();
       
   770 	//"File I/O" error simulation loop
       
   771 	err = KErrCorrupt;
       
   772 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   773 		{
       
   774 		TheTest.Printf(_L("%d \r"), cnt);		
       
   775 		TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   776 		(void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
       
   777 		RSqlDatabase::TSize size2 = {-1, -1};
       
   778 		err = TheDb.Size(size2);
       
   779 		(void)TheFs.SetErrorCondition(KErrNone);
       
   780 		TheDb.Close();
       
   781 		if(err == KErrNone)
       
   782 			{
       
   783 			TEST(size2.iSize == size1.iSize);
       
   784 			TEST(size2.iFree == size1.iFree);
       
   785 			break;
       
   786 			}
       
   787 		else
       
   788 			{
       
   789 			//check the database content - all bets are off in a case of an I/O error. 
       
   790 			TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   791 			TSqlScalarFullSelectQuery q(TheDb);
       
   792 			TInt recCnt = 0;
       
   793 			TRAPD(err2, recCnt = q.SelectIntL(_L8("SELECT COUNT(*) FROM A")));
       
   794 			TheDb.Close();
       
   795 			TEST2(err2, KErrNone);
       
   796 			TEST2(recCnt, 1);
       
   797 			}
       
   798 		}
       
   799 	(void)RSqlDatabase::Delete(KTestDbName);
       
   800 	}
       
   801 
       
   802 /**
       
   803 @SYMTestCaseID			SYSLIB-SQL-UT-4045
       
   804 @SYMTestCaseDesc		RSqlDatabase::Compact(), file I/O error simulation test.
       
   805 						The test creates a database and executes RSqlDatabase::Compact()
       
   806 						during a file I/O error simulation. The database should not be corrupted 
       
   807 						by the call.
       
   808 @SYMTestPriority		High
       
   809 @SYMTestActions			RSqlDatabase::Compact(), file I/O error simulation test.
       
   810 @SYMTestExpectedResults Test must not fail
       
   811 @SYMREQ					REQ10405
       
   812 */
       
   813 void CompactTest()
       
   814 	{
       
   815 	(void)RSqlDatabase::Delete(KTestDbName);
       
   816 	_LIT8(KConfig, "compaction=manual");
       
   817 	TInt err = TheDb.Create(KTestDbName, &KConfig);
       
   818 	TEST2(err, KErrNone);
       
   819 	err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Data BLOB)"));
       
   820 	TEST(err >= 0);
       
   821 	//Insert records
       
   822 	err = TheDb.Exec(_L8("BEGIN"));
       
   823 	TEST(err >= 0);
       
   824 	const TInt KRecLen = 1000;
       
   825 	TBuf8<KRecLen> sqlfmt;
       
   826 	sqlfmt.Copy(_L8("INSERT INTO A VALUES(%d,x'"));
       
   827 	for(TInt j=0;j<(KRecLen-50);++j)
       
   828 		{
       
   829 		sqlfmt.Append(_L8("A"));
       
   830 		}
       
   831 	sqlfmt.Append(_L8("')"));
       
   832 	const TInt KRecCount = 100;	
       
   833 	for(TInt i=0;i<KRecCount;++i)
       
   834 		{
       
   835 		TBuf8<KRecLen> sql;
       
   836 		sql.Format(sqlfmt, i + 1);
       
   837 		err = TheDb.Exec(sql);
       
   838 		TEST2(err, 1);
       
   839 		}
       
   840 	err = TheDb.Exec(_L8("COMMIT"));
       
   841 	TEST(err >= 0);
       
   842 	//Free some space
       
   843 	const TInt KDeletedRecCnt = KRecCount - 10;
       
   844 	err = TheDb.Exec(_L8("DELETE FROM A WHERE Id > 10"));
       
   845 	TEST(err >= 0);
       
   846 	//Get the database size
       
   847 	RSqlDatabase::TSize size;
       
   848 	err = TheDb.Size(size);
       
   849 	TEST2(err, KErrNone);
       
   850 	TheDb.Close();
       
   851 	TEST(size.iSize > 0);
       
   852 	TEST(size.iFree > 0);
       
   853 	//"File I/O" error simulation loop
       
   854 	err = KErrCorrupt;
       
   855 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   856 		{
       
   857 		TheTest.Printf(_L("%d \r"), cnt);		
       
   858 		TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   859 		(void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
       
   860 		err = TheDb.Compact(RSqlDatabase::EMaxCompaction);
       
   861 		(void)TheFs.SetErrorCondition(KErrNone);
       
   862 		TheDb.Close();
       
   863 		if(err == KErrNone)
       
   864 			{
       
   865 			break;
       
   866 			}
       
   867 		else
       
   868 			{
       
   869 			//check the database content - all bets are off in a case of an I/O error. 
       
   870 			//The database maight have been compacted, so - no check for that.
       
   871 			TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   872 			TSqlScalarFullSelectQuery q(TheDb);
       
   873 			TInt recCnt = 0;
       
   874 			TRAPD(err2, recCnt = q.SelectIntL(_L8("SELECT COUNT(*) FROM A")));
       
   875 			TheDb.Close();
       
   876 			TEST2(err2, KErrNone);
       
   877 			TEST2(recCnt, (KRecCount - KDeletedRecCnt));
       
   878 			}
       
   879 		}
       
   880 	TheTest.Printf(_L("\r\n"));
       
   881 	//Check that the database has been really compacted
       
   882 	TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   883 	RSqlDatabase::TSize size2;
       
   884 	err = TheDb.Size(size2);
       
   885 	TEST2(err, KErrNone);
       
   886 	TheDb.Close();
       
   887 	(void)RSqlDatabase::Delete(KTestDbName);
       
   888 	TEST(size.iSize > size2.iSize);
       
   889 	TEST2(size2.iFree, 0);
       
   890 	}
       
   891 
       
   892 void DoBlobWriteStreamTestL(TBool aAttachDb)
       
   893 	{
       
   894 	RSqlBlobWriteStream strm;
       
   895 	CleanupClosePushL(strm);
       
   896 	if(aAttachDb)
       
   897 		{
       
   898 		strm.OpenL(TheDb, _L("A"), _L("Data"), 1, KAttachDb);
       
   899 		}
       
   900 	else
       
   901 		{
       
   902 		strm.OpenL(TheDb, _L("A"), _L("Data"), 1);
       
   903 		}
       
   904 
       
   905 	TBuf8<KBlobSize / KWriteCnt> data;
       
   906 	data.SetLength(KBlobSize / KWriteCnt);
       
   907 	data.Fill(0xA5);
       
   908 	
       
   909 	for(TInt i=0;i<KWriteCnt;++i)
       
   910 		{
       
   911 		strm.WriteL(data);
       
   912 		}
       
   913 	
       
   914 	strm.CommitL();
       
   915 	
       
   916 	CleanupStack::PopAndDestroy(&strm);
       
   917 	}
       
   918 
       
   919 /**
       
   920 @SYMTestCaseID			SYSLIB-SQL-UT-4089
       
   921 @SYMTestCaseDesc		RSqlBlobWriteStream::WriteL(), file I/O error simulation test.
       
   922 						The test creates a database and executes RSqlBlobWriteStream::WriteL()
       
   923 						during a file I/O error simulation. The database should not be corrupted 
       
   924 						by the call.
       
   925 @SYMTestPriority		High
       
   926 @SYMTestActions			RSqlBlobWriteStream::WriteL(), file I/O error simulation test.
       
   927 @SYMTestExpectedResults Test must not fail
       
   928 @SYMREQ					REQ5792
       
   929                         REQ10418
       
   930 */
       
   931 void BlobWriteStreamTest(TBool aAttachDb)
       
   932 	{
       
   933 	(void)RSqlDatabase::Delete(KTestDbName);
       
   934 	TInt err = TheDb.Create(KTestDbName);
       
   935 	TEST2(err, KErrNone);
       
   936 	err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Data BLOB)"));
       
   937 	TEST2(err, 1);
       
   938 	TBuf8<100> sql;
       
   939 	sql.Format(_L8("INSERT INTO A VALUES(1, zeroblob(%d))"), KBlobSize);
       
   940 	err = TheDb.Exec(sql);
       
   941 	TEST2(err, 1);
       
   942 	TheDb.Close();
       
   943 	
       
   944 	err = KErrCorrupt;
       
   945 	for(TInt cnt=1;err<KErrNone;++cnt)
       
   946 		{
       
   947 		TheTest.Printf(_L("%d \r"), cnt);		
       
   948 		TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   949 		if(aAttachDb)
       
   950 			{
       
   951 			TEST2(TheDb.Attach(KTestDbName, KAttachDb), KErrNone);	
       
   952 			}
       
   953 		(void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
       
   954 		TRAP(err, DoBlobWriteStreamTestL(aAttachDb));
       
   955 		(void)TheFs.SetErrorCondition(KErrNone);
       
   956 		if(aAttachDb)
       
   957 			{
       
   958 			TEST2(TheDb.Detach(KAttachDb), KErrNone);	
       
   959 			}
       
   960 		TheDb.Close();
       
   961 		}
       
   962 	TheTest.Printf(_L("\r\n"));
       
   963 
       
   964 	TEST2(TheDb.Open(KTestDbName), KErrNone);
       
   965 	
       
   966 	RSqlStatement stmt;
       
   967 	err = stmt.Prepare(TheDb, _L8("SELECT * FROM A"));
       
   968 	TEST2(err, KErrNone);
       
   969 	err = stmt.Next();
       
   970 	TEST2(err, KSqlAtRow);
       
   971 	TPtrC8 data;
       
   972 	err = stmt.ColumnBinary(1, data);
       
   973 	TEST2(err, KErrNone);
       
   974 	TEST2(data.Length(), KBlobSize);
       
   975 	for(TInt j=0;j<KBlobSize;++j)
       
   976 		{
       
   977 		TUint8 d = data[j];
       
   978 		TEST2(d, 0xA5);	
       
   979 		}
       
   980 	stmt.Close();
       
   981 	
       
   982 	TheDb.Close();
       
   983 	(void)RSqlDatabase::Delete(KTestDbName);
       
   984 	}
       
   985 
       
   986 void DoBlobReadStreamTestL(TBool aAttachDb, TDes8& aDes)
       
   987 	{
       
   988 	RSqlBlobReadStream strm;
       
   989 	CleanupClosePushL(strm);
       
   990 	if(aAttachDb)
       
   991 		{
       
   992 		strm.OpenL(TheDb, _L("A"), _L("Data"), 1, KAttachDb);
       
   993 		}
       
   994 	else
       
   995 		{
       
   996 		strm.OpenL(TheDb, _L("A"), _L("Data"), 1);
       
   997 		}
       
   998 
       
   999 	TBuf8<KBlobSize / KWriteCnt> data;
       
  1000 	aDes.SetLength(0);
       
  1001 	
       
  1002 	for(TInt i=0;i<KWriteCnt;++i)
       
  1003 		{
       
  1004 		strm.ReadL(data);
       
  1005 		aDes.Append(data);
       
  1006 		}
       
  1007 	
       
  1008 	CleanupStack::PopAndDestroy(&strm);
       
  1009 	}
       
  1010 
       
  1011 /**
       
  1012 @SYMTestCaseID			SYSLIB-SQL-UT-4090
       
  1013 @SYMTestCaseDesc		RSqlBlobReadStream::ReadL(), file I/O error simulation test.
       
  1014 						The test creates a database and executes RSqlBlobReadStream::ReadL()
       
  1015 						during a file I/O error simulation. The database should not be corrupted 
       
  1016 						by the call.
       
  1017 @SYMTestPriority		High
       
  1018 @SYMTestActions			RSqlBlobReadStream::ReadL(), file I/O error simulation test.
       
  1019 @SYMTestExpectedResults Test must not fail
       
  1020 @SYMREQ					REQ5792
       
  1021                         REQ10410
       
  1022                         REQ10411
       
  1023 */
       
  1024 void BlobReadStreamTest(TBool aAttachDb)
       
  1025 	{
       
  1026 	(void)RSqlDatabase::Delete(KTestDbName);
       
  1027 	TInt err = TheDb.Create(KTestDbName);
       
  1028 	TEST2(err, KErrNone);
       
  1029 	err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Data BLOB)"));
       
  1030 	TEST2(err, 1);
       
  1031 	TBuf8<100> sql;
       
  1032 	sql.Format(_L8("INSERT INTO A VALUES(1, zeroblob(%d))"), KBlobSize);
       
  1033 	err = TheDb.Exec(sql);
       
  1034 	TEST2(err, 1);
       
  1035 	TRAP(err, DoBlobWriteStreamTestL(EFalse));
       
  1036 	TEST2(err, KErrNone);
       
  1037 	TheDb.Close();
       
  1038 	
       
  1039 	HBufC8* buf = HBufC8::New(KBlobSize);
       
  1040 	TEST(buf != NULL);
       
  1041 	TPtr8 bufptr = buf->Des();
       
  1042 	
       
  1043 	err = KErrCorrupt;
       
  1044 	for(TInt cnt=1;err<KErrNone;++cnt)
       
  1045 		{
       
  1046 		TheTest.Printf(_L("%d \r"), cnt);		
       
  1047 		TEST2(TheDb.Open(KTestDbName), KErrNone);
       
  1048 		if(aAttachDb)
       
  1049 			{
       
  1050 			TEST2(TheDb.Attach(KTestDbName, KAttachDb), KErrNone);	
       
  1051 			}
       
  1052 		(void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
       
  1053 		TRAP(err, DoBlobReadStreamTestL(aAttachDb, bufptr));
       
  1054 		(void)TheFs.SetErrorCondition(KErrNone);
       
  1055 		if(aAttachDb)
       
  1056 			{
       
  1057 			TEST2(TheDb.Detach(KAttachDb), KErrNone);	
       
  1058 			}
       
  1059 		TheDb.Close();
       
  1060 		}
       
  1061 	TheTest.Printf(_L("\r\n"));
       
  1062 
       
  1063 	TEST2(bufptr.Length(), KBlobSize);
       
  1064 	for(TInt j=0;j<KBlobSize;++j)
       
  1065 		{
       
  1066 		TUint8 d = bufptr[j];
       
  1067 		TEST2(d, 0xA5);	
       
  1068 		}
       
  1069 		
       
  1070 	delete buf;
       
  1071 		
       
  1072 	(void)RSqlDatabase::Delete(KTestDbName);
       
  1073 	}
       
  1074 
       
  1075 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1076 
       
  1077 void DoTests()
       
  1078 	{
       
  1079 	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3419 Alter database during file I/O error "));
       
  1080 	AlterDatabaseTest();
       
  1081 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3420 Alter database during file I/O error (using statement object) "));
       
  1082 	AlterDatabaseTest2();
       
  1083 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3421 Open database during file I/O error "));
       
  1084 	OpenDatabaseTest();
       
  1085 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3434 Create database during file I/O error "));
       
  1086 	CreateDatabaseTest();
       
  1087 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3462 Select record test during file I/O error "));
       
  1088 	SelectRecordTest();
       
  1089 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3463 Insert record test during file I/O error "));
       
  1090 	InsertRecordTest();
       
  1091 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3516 Removable Media robustness test "));
       
  1092 	RemovableMediaRobustnessTest();
       
  1093 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4044 Database size test during file I/O error"));	
       
  1094 	SizeTest();
       
  1095 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4045 Compact database test during file I/O error"));	
       
  1096 	CompactTest();
       
  1097 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4089 RSqlBlobWriteStream::WriteL() test during file I/O error"));	
       
  1098 	BlobWriteStreamTest(EFalse);
       
  1099 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4089 RSqlBlobWriteStream::WriteL()+attached database test during file I/O error"));	
       
  1100 	BlobWriteStreamTest(ETrue);
       
  1101 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4090 RSqlBlobReadStream::ReadL() test during file I/O error"));	
       
  1102 	BlobReadStreamTest(EFalse);
       
  1103 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4090 RSqlBlobReadStream::ReadL()+attached database test during file I/O error"));	
       
  1104 	BlobReadStreamTest(ETrue);
       
  1105 	}
       
  1106 
       
  1107 TInt E32Main()
       
  1108 	{
       
  1109 	TheTest.Title();
       
  1110 	
       
  1111 	CTrapCleanup* tc = CTrapCleanup::New();
       
  1112 	
       
  1113 	__UHEAP_MARK;
       
  1114 	
       
  1115 	SetupTestEnv();
       
  1116 	DoTests();
       
  1117 	DestroyTestEnv();
       
  1118 	
       
  1119 	__UHEAP_MARKEND;
       
  1120 	
       
  1121 	TheTest.End();
       
  1122 	TheTest.Close();
       
  1123 	
       
  1124 	delete tc;
       
  1125 	
       
  1126 	User::Heap().Check();
       
  1127 	return KErrNone;
       
  1128 	}