1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sql/TEST/t_sqlfserr.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1263 @@
1.4 +// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <e32test.h>
1.20 +#include <bautils.h>
1.21 +#include <sqldb.h>
1.22 +#include <stdio.h>
1.23 +#include <stdlib.h>
1.24 +#include <string.h>
1.25 +#include "sqlite3.h"
1.26 +#include "SqliteSymbian.h"
1.27 +
1.28 +///////////////////////////////////////////////////////////////////////////////////////
1.29 +
1.30 +RTest TheTest(_L("t_sqlfserr test"));
1.31 +_LIT(KTestDir, "c:\\test\\");
1.32 +_LIT(KTestDbName, "c:\\test\\t_fserr.db");
1.33 +_LIT(KPrivateTestDbName, "c:\\private\\212A2C27\\t_fserr2.db");
1.34 +_LIT(KSecureTestDbName, "c:[212A2C27]t_fserr3.db");
1.35 +
1.36 +TFileName TheRmvMediaDbFileName;//The name of the file used for tests on a removable media
1.37 +RFs TheFs;
1.38 +RSqlDatabase TheDb;
1.39 +
1.40 +//The next constants are used in the "blob write" test
1.41 +const TInt KWriteCnt = 9;
1.42 +const TInt KBlobSize = 397 * KWriteCnt;
1.43 +_LIT(KAttachDb, "AttachDb");
1.44 +
1.45 +//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)
1.46 +#ifdef _SQLPROFILER
1.47 +TInt TheSqlSrvProfilerFileRead = 0;
1.48 +TInt TheSqlSrvProfilerFileWrite = 0;
1.49 +TInt TheSqlSrvProfilerFileSync = 0;
1.50 +TInt TheSqlSrvProfilerFileSetSize = 0;
1.51 +#endif
1.52 +
1.53 +///////////////////////////////////////////////////////////////////////////////////////
1.54 +
1.55 +TBool FileExists(const TDesC& aFileName)
1.56 + {
1.57 + TEntry entry;
1.58 + return TheFs.Entry(aFileName, entry) == KErrNone;
1.59 + }
1.60 +
1.61 +void DestroyTestEnv()
1.62 + {
1.63 + TheDb.Close();
1.64 + (void)RSqlDatabase::Delete(KSecureTestDbName);
1.65 + (void)RSqlDatabase::Delete(KPrivateTestDbName);
1.66 + (void)RSqlDatabase::Delete(KTestDbName);
1.67 + (void)RSqlDatabase::Delete(TheRmvMediaDbFileName);
1.68 + TheFs.Close();
1.69 + sqlite3SymbianLibFinalize();
1.70 + CloseSTDLIB();
1.71 + }
1.72 +
1.73 +///////////////////////////////////////////////////////////////////////////////////////
1.74 +///////////////////////////////////////////////////////////////////////////////////////
1.75 +//Test macros and functions
1.76 +void Check(TInt aValue, TInt aLine)
1.77 + {
1.78 + if(!aValue)
1.79 + {
1.80 + DestroyTestEnv();
1.81 + TheTest(EFalse, aLine);
1.82 + }
1.83 + }
1.84 +void Check(TInt aValue, TInt aExpected, TInt aLine)
1.85 + {
1.86 + if(aValue != aExpected)
1.87 + {
1.88 + DestroyTestEnv();
1.89 + RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
1.90 + TheTest(EFalse, aLine);
1.91 + }
1.92 + }
1.93 +#define TEST(arg) ::Check((arg), __LINE__)
1.94 +#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
1.95 +
1.96 +void SqliteCheck(sqlite3* aDbHandle, TInt aValue, TInt aExpected, TInt aLine)
1.97 + {
1.98 + if(aValue != aExpected)
1.99 + {
1.100 + RDebug::Print(_L("*** SQLITE: Expected error: %d, got: %d\r\n"), aExpected, aValue);
1.101 + if(aDbHandle)
1.102 + {
1.103 + const char* errMsg = sqlite3_errmsg(aDbHandle);
1.104 + TPtrC8 ptr8((const TUint8*)errMsg, strlen(errMsg));
1.105 + TBuf<200> buf;
1.106 + buf.Copy(ptr8);
1.107 + RDebug::Print(_L("*** SQLITE error message: \"%S\"\r\n"), &buf);
1.108 + }
1.109 + DestroyTestEnv();
1.110 + TheTest(EFalse, aLine);
1.111 + }
1.112 + }
1.113 +#define SQLITE_TEST(aDbHandle, aValue, aExpected) ::SqliteCheck(aDbHandle, aValue, aExpected, __LINE__)
1.114 +
1.115 +///////////////////////////////////////////////////////////////////////////////////////
1.116 +
1.117 +void SetupTestEnv()
1.118 + {
1.119 + TInt err = TheFs.Connect();
1.120 + TEST2(err, KErrNone);
1.121 +
1.122 + err = TheFs.MkDir(KTestDir);
1.123 + TEST(err == KErrNone || err == KErrAlreadyExists);
1.124 +
1.125 + sqlite3SymbianLibInit();
1.126 + }
1.127 +
1.128 +TBool CheckRecord(const TDesC& aDbName, TInt aId, const TDesC& aExpectedName, TBool aOpenDb = ETrue)
1.129 + {
1.130 + if(aOpenDb)
1.131 + {
1.132 + TEST2(TheDb.Open(aDbName), KErrNone);
1.133 + }
1.134 + TBuf<64> sql;
1.135 + sql.Copy(_L("SELECT Name FROM A WHERE Id="));
1.136 + sql.AppendNum(aId);
1.137 + TSqlScalarFullSelectQuery q(TheDb);
1.138 + TBuf<20> name;
1.139 + TRAPD(err, (void)q.SelectTextL(sql, name));
1.140 + TEST2(err, KErrNone);
1.141 + if(aOpenDb)
1.142 + {
1.143 + TheDb.Close();
1.144 + }
1.145 + return name == aExpectedName;
1.146 + }
1.147 +
1.148 +///////////////////////////////////////////////////////////////////////////////////////
1.149 +
1.150 +/**
1.151 +@SYMTestCaseID SYSLIB-SQL-UT-3419
1.152 +@SYMTestCaseDesc Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
1.153 + The test creates a test database with one table, inserts one record.
1.154 + Then the test attempts to update the existing record while simulating file I/O failures.
1.155 + After each test iteration the database content is tested and is expected to be the same
1.156 + as it was before the test. RSqlDatabase::Exec() is used for the update operation.
1.157 +@SYMTestPriority High
1.158 +@SYMTestActions Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
1.159 +@SYMTestExpectedResults The test must not fail
1.160 +@SYMDEF DEF103859
1.161 +*/
1.162 +void AlterDatabaseTest()
1.163 + {
1.164 + (void)RSqlDatabase::Delete(KTestDbName);
1.165 + TInt err = TheDb.Create(KTestDbName);
1.166 + TEST2(err, KErrNone);
1.167 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT)"));
1.168 + TEST(err >= 0);
1.169 + TheDb.Close();
1.170 + err = KErrNotFound;
1.171 + for(TInt cnt=0;err<KErrNone;++cnt)
1.172 + {
1.173 + TheTest.Printf(_L("%d \r"), cnt);
1.174 + for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
1.175 + {
1.176 + //Preprocessing
1.177 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.178 + (void)TheDb.Exec(_L("DELETE FROM A WHERE Id=1"));
1.179 + err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
1.180 + TEST2(err, 1);
1.181 + //The test
1.182 + (void)TheFs.SetErrorCondition(fsError, cnt);
1.183 + err = TheDb.Exec(_L("UPDATE A SET Name='Name2' WHERE Id=1"));
1.184 + (void)TheFs.SetErrorCondition(KErrNone);
1.185 + if(err < 1)
1.186 + {
1.187 + TheDb.Close();//close the database to recover from the last error
1.188 + //check the database content - all bets are off in a case of an I/O error.
1.189 + //The existing record might have been updated.
1.190 + TEST(CheckRecord(KTestDbName, 1, _L("Name")) || CheckRecord(KTestDbName, 1, _L("Name2")));
1.191 + }
1.192 + else
1.193 + {
1.194 + TEST2(err, 1);
1.195 + //check the database content has been modified by the operation.
1.196 + TEST(CheckRecord(KTestDbName, 1, _L("Name2"), EFalse));
1.197 + TheDb.Close();
1.198 + }
1.199 + }
1.200 + }
1.201 + (void)TheFs.SetErrorCondition(KErrNone);
1.202 + TEST2(err, 1);
1.203 + //check the database content (transaction durability).
1.204 + TEST(CheckRecord(KTestDbName, 1, _L("Name2")));
1.205 + err = RSqlDatabase::Delete(KTestDbName);
1.206 + TEST2(err, KErrNone);
1.207 + TheTest.Printf(_L("\r\n"));
1.208 + }
1.209 +
1.210 +/**
1.211 +@SYMTestCaseID SYSLIB-SQL-UT-3420
1.212 +@SYMTestCaseDesc Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
1.213 + The test creates a test database with one table, inserts one record.
1.214 + Then the test attempts to update the existing record while simulating file I/O failures.
1.215 + After each test iteration the database content is tested and is expected to be the same
1.216 + as it was before the test. RSqlStatement::Exec() is used for the update operation.
1.217 +@SYMTestPriority High
1.218 +@SYMTestActions Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
1.219 +@SYMTestExpectedResults The test must not fail
1.220 +@SYMDEF DEF103859
1.221 +*/
1.222 +void AlterDatabaseTest2()
1.223 + {
1.224 + (void)RSqlDatabase::Delete(KTestDbName);
1.225 + TInt err = TheDb.Create(KTestDbName);
1.226 + TEST2(err, KErrNone);
1.227 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT)"));
1.228 + TEST(err >= 0);
1.229 + TheDb.Close();
1.230 + err = KErrNotFound;
1.231 + for(TInt cnt=0;err<KErrNone;++cnt)
1.232 + {
1.233 + TheTest.Printf(_L("%d \r"), cnt);
1.234 + for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
1.235 + {
1.236 + //Preprocessing
1.237 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.238 + (void)TheDb.Exec(_L("DELETE FROM A WHERE Id=1"));
1.239 + err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
1.240 + TEST2(err, 1);
1.241 + //The test
1.242 + (void)TheFs.SetErrorCondition(fsError, cnt);
1.243 + RSqlStatement stmt;
1.244 + err = stmt.Prepare(TheDb, _L("UPDATE A SET Name='Name2' WHERE Id=1"));
1.245 + if(err == KErrNone)
1.246 + {
1.247 + err = stmt.Exec();
1.248 + }
1.249 + (void)TheFs.SetErrorCondition(KErrNone);
1.250 + stmt.Close();
1.251 + if(err < 1)
1.252 + {
1.253 + TheDb.Close();//close the database to recover from the last error
1.254 + //check the database content - all bets are off in a case of an I/O error.
1.255 + //The existing record might have been updated.
1.256 + TEST(CheckRecord(KTestDbName, 1, _L("Name")) || CheckRecord(KTestDbName, 1, _L("Name2")));
1.257 + }
1.258 + else
1.259 + {
1.260 + TEST2(err, 1);
1.261 + //check the database content has been modified by the operation.
1.262 + TEST(CheckRecord(KTestDbName, 1, _L("Name2"), EFalse));
1.263 + TheDb.Close();
1.264 + }
1.265 + }
1.266 + }
1.267 + (void)TheFs.SetErrorCondition(KErrNone);
1.268 + TEST2(err, 1);
1.269 + //check the database content has been modified by the operation.
1.270 + TEST(CheckRecord(KTestDbName, 1, _L("Name2")));
1.271 + err = RSqlDatabase::Delete(KTestDbName);
1.272 + TEST2(err, KErrNone);
1.273 + TheTest.Printf(_L("\r\n"));
1.274 + }
1.275 +
1.276 +void CreateTestSecurityPolicy(RSqlSecurityPolicy& aSecurityPolicy)
1.277 + {
1.278 + TSecurityPolicy alwaysPassPolicy(TSecurityPolicy::EAlwaysPass);
1.279 + TInt err = aSecurityPolicy.Create(alwaysPassPolicy);
1.280 + TEST2(err, KErrNone);
1.281 +
1.282 + err = aSecurityPolicy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy, alwaysPassPolicy);
1.283 + TEST2(err, KErrNone);
1.284 + err = aSecurityPolicy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy, alwaysPassPolicy);
1.285 + TEST2(err, KErrNone);
1.286 + err = aSecurityPolicy.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy, alwaysPassPolicy);
1.287 + TEST2(err, KErrNone);
1.288 + }
1.289 +
1.290 +//Creates public shared, private secure and public secure databases.
1.291 +void DoCreateTestDatabases(const TPtrC aDbName[], TInt aCount)
1.292 + {
1.293 + TEST(aCount > 0);
1.294 + for(TInt i=0;i<aCount;++i)
1.295 + {
1.296 + TheTest.Printf(_L("Database: \"%S\"\r\n"), &aDbName[i]);
1.297 + (void)RSqlDatabase::Delete(aDbName[i]);
1.298 + TInt err = KErrGeneral;
1.299 + if(i == (aCount - 1))
1.300 + {
1.301 + RSqlSecurityPolicy policy;
1.302 + CreateTestSecurityPolicy(policy);
1.303 + err = TheDb.Create(aDbName[i], policy);
1.304 + policy.Close();
1.305 + }
1.306 + else
1.307 + {
1.308 + err = TheDb.Create(aDbName[i]);
1.309 + }
1.310 + TEST2(err, KErrNone);
1.311 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT)"));
1.312 + TEST(err >= 0);
1.313 + err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
1.314 + TEST2(err, 1);
1.315 + TheDb.Close();
1.316 + }
1.317 + }
1.318 +
1.319 +/**
1.320 +@SYMTestCaseID SYSLIB-SQL-UT-3421
1.321 +@SYMTestCaseDesc Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
1.322 + The test creates a test database with one table, inserts one record.
1.323 + Then the test attempts to open the database while simulating file I/O failures.
1.324 + At the end of the test the database content is tested and is expected to be the same
1.325 + as it was before the test. RSqlStatement::Open() is used in the test.
1.326 +@SYMTestPriority High
1.327 +@SYMTestActions Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
1.328 +@SYMTestExpectedResults The test must not fail
1.329 +@SYMDEF DEF103859
1.330 +*/
1.331 +void OpenDatabaseTest()
1.332 + {
1.333 + TPtrC dbName[] = {KTestDbName(), KPrivateTestDbName(), KSecureTestDbName()};
1.334 + const TInt KDbNameCnt = sizeof(dbName) / sizeof(dbName[0]);
1.335 + DoCreateTestDatabases(dbName, KDbNameCnt);
1.336 + for(TInt k=0;k<KDbNameCnt;++k)
1.337 + {
1.338 + TheTest.Printf(_L("Database: \"%S\"\r\n"), &dbName[k]);
1.339 + TInt err = KErrNotFound;
1.340 + for(TInt cnt=0;err<KErrNone;++cnt)
1.341 + {
1.342 + TheTest.Printf(_L("%d \r"), cnt);
1.343 + for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
1.344 + {
1.345 + (void)TheFs.SetErrorCondition(fsError, cnt);
1.346 + err = TheDb.Open(dbName[k]);
1.347 + (void)TheFs.SetErrorCondition(KErrNone);
1.348 + if(err != KErrNone)
1.349 + {
1.350 + TheDb.Close();//close the database to recover from the last error
1.351 + //check the database content is still the same as before the "open" call
1.352 + TEST(CheckRecord(dbName[k], 1, _L("Name")));
1.353 + }
1.354 + else
1.355 + {
1.356 + TEST2(err, KErrNone);
1.357 + //check the database content is still the same as before the operation, without closing the database
1.358 + TEST(CheckRecord(dbName[k], 1, _L("Name"), EFalse));
1.359 + TheDb.Close();
1.360 + }
1.361 + }
1.362 + }
1.363 + (void)TheFs.SetErrorCondition(KErrNone);
1.364 + TEST2(err, KErrNone);
1.365 + //check the database content is the same as before the operation, after reopening the database.
1.366 + TEST(CheckRecord(dbName[k], 1, _L("Name")));
1.367 + err = RSqlDatabase::Delete(dbName[k]);
1.368 + TEST2(err, KErrNone);
1.369 + TheTest.Printf(_L("\r\n"));
1.370 + }//end of: for(TInt k=0;k<KDbNameCnt;++k)
1.371 + }
1.372 +
1.373 +/**
1.374 +@SYMTestCaseID SYSLIB-SQL-UT-3434
1.375 +@SYMTestCaseDesc Test for DEF104820 "SQL, RSqlDatabase::Create() does not delete the file if fails".
1.376 + Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
1.377 + Then the test attempts to create a database while simulating file I/O failures.
1.378 + When the test succeeds, the test verifies that the database file does exist.
1.379 +@SYMTestPriority High
1.380 +@SYMTestActions Test for DEF104820 "SQL, RSqlDatabase::Create() does not delete the file if fails".
1.381 + Test for DEF103859 "SQLITE panic, _DEBUG mode, persistent file I/O error simulation".
1.382 +@SYMTestExpectedResults The test must not fail
1.383 +@SYMDEF DEF103859
1.384 +*/
1.385 +void CreateDatabaseTest()
1.386 + {
1.387 + RSqlSecurityPolicy policy;
1.388 + CreateTestSecurityPolicy(policy);
1.389 +
1.390 + TPtrC dbName[] = {KTestDbName(), KPrivateTestDbName(), KSecureTestDbName()};
1.391 + const TInt KDbNameCnt = sizeof(dbName) / sizeof(dbName[0]);
1.392 + for(TInt k=0;k<KDbNameCnt;++k)
1.393 + {
1.394 + TheTest.Printf(_L("Database: \"%S\"\r\n"), &dbName[k]);
1.395 + TInt err = -1;
1.396 + for(TInt cnt=0;err<KErrNone;++cnt)
1.397 + {
1.398 + TheTest.Printf(_L("%d \r"), cnt);
1.399 + for (TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
1.400 + {
1.401 + //Ideally, the database should be deleted by the SQL server, if RSqlDatabase::Create() fails.
1.402 + //But SetErrorCondition() makes the error persistent, so the SQL server will fail to delete the file.
1.403 + //This is the reason, RSqlDatabase::Delete()to be used, before simulating file I/O error.
1.404 + (void)RSqlDatabase::Delete(dbName[k]);
1.405 + (void)TheFs.SetErrorCondition(fsError, cnt);
1.406 + err = (k == (KDbNameCnt - 1)) ? TheDb.Create(dbName[k], policy) : TheDb.Create(dbName[k]);
1.407 + (void)TheFs.SetErrorCondition(KErrNone);
1.408 + TheDb.Close();
1.409 + //If err != KErrNone, the database file should have been already deleted by the server and here is
1.410 + //the place to check that. But since the file I/O failure simulation makes the file I/O error
1.411 + //persistent, the file cannot be deleted by the server, because the "file delete" operation also fails.
1.412 + }
1.413 + }
1.414 + (void)TheFs.SetErrorCondition(KErrNone);
1.415 + TheDb.Close();
1.416 + TEST2(err, KErrNone);
1.417 + if( k != (KDbNameCnt - 1))
1.418 + {
1.419 + TEST(FileExists(dbName[k]));
1.420 + }
1.421 + err = RSqlDatabase::Delete(dbName[k]);
1.422 + TEST2(err, KErrNone);
1.423 + TheTest.Printf(_L("\r\n"));
1.424 + }
1.425 + policy.Close();
1.426 + }
1.427 +
1.428 +/**
1.429 +@SYMTestCaseID PDS-SQL-UT-4189
1.430 +@SYMTestCaseDesc Test for DEF145125 "SQL, low code coverage".
1.431 + The test creates public shared, private secure and public secure test databases.
1.432 + Then the test opens the publich shared database and attempts to attach one of the other two
1.433 + in a file I/O error simulation loop.
1.434 +@SYMTestPriority High
1.435 +@SYMTestActions Test for DEF145125 - "SQL, low code coverage".
1.436 +@SYMTestExpectedResults The test must not fail
1.437 +@SYMDEF DEF145125
1.438 +*/
1.439 +void AttachDatabaseTest()
1.440 + {
1.441 + TPtrC dbName[] = {KTestDbName(), KPrivateTestDbName(), KSecureTestDbName()};
1.442 + const TInt KDbNameCnt = sizeof(dbName) / sizeof(dbName[0]);
1.443 + DoCreateTestDatabases(dbName, KDbNameCnt);
1.444 + for(TInt k=1;k<KDbNameCnt;++k)
1.445 + {
1.446 + TheTest.Printf(_L("Database: \"%S\"\r\n"), &dbName[k]);
1.447 + TInt err = KErrGeneral;
1.448 + for(TInt cnt=0;err<KErrNone;++cnt)
1.449 + {
1.450 + TheTest.Printf(_L("%d \r"), cnt);
1.451 + for(TInt fsError=KErrNotFound;fsError>=KErrDied;--fsError)
1.452 + {
1.453 + err = TheDb.Open(KTestDbName);
1.454 + TEST2(err, KErrNone);
1.455 + (void)TheFs.SetErrorCondition(fsError, cnt);
1.456 + err = TheDb.Attach(dbName[k], _L("DB2"));
1.457 + (void)TheFs.SetErrorCondition(KErrNone);
1.458 + (void)TheDb.Detach(_L("DB2"));
1.459 + TheDb.Close();//close the database to recover from the last error
1.460 + }
1.461 + }
1.462 + TEST2(err, KErrNone);
1.463 + err = RSqlDatabase::Delete(dbName[k]);
1.464 + TEST2(err, KErrNone);
1.465 + TheTest.Printf(_L("\r\n"));
1.466 + }
1.467 + }
1.468 +
1.469 +/**
1.470 +@SYMTestCaseID PDS-SQL-UT-4190
1.471 +@SYMTestCaseDesc Test for DEF145125 "SQL, low code coverage".
1.472 + The tests attempts to delete a database in a file I/O error simulation loop.
1.473 +@SYMTestPriority High
1.474 +@SYMTestActions Test for DEF145125 - "SQL, low code coverage".
1.475 +@SYMTestExpectedResults The test must not fail
1.476 +@SYMDEF DEF145125
1.477 +*/
1.478 +void DeleteDatabaseTest()
1.479 + {
1.480 + TPtrC dbName[] = {KTestDbName(), KPrivateTestDbName(), KSecureTestDbName()};
1.481 + const TInt KDbNameCnt = sizeof(dbName) / sizeof(dbName[0]);
1.482 + DoCreateTestDatabases(dbName, KDbNameCnt);
1.483 + for(TInt k=0;k<KDbNameCnt;++k)
1.484 + {
1.485 + TheTest.Printf(_L("Database: \"%S\"\r\n"), &dbName[k]);
1.486 + TInt err = KErrGeneral;
1.487 + for(TInt cnt=1;err<KErrNone;++cnt)
1.488 + {
1.489 + TheTest.Printf(_L("%d \r"), cnt);
1.490 + (void)TheFs.SetErrorCondition(KErrGeneral, cnt);
1.491 + err = RSqlDatabase::Delete(dbName[k]);
1.492 + (void)TheFs.SetErrorCondition(KErrNone);
1.493 + }
1.494 + TEST2(err, KErrNone);
1.495 + err = RSqlDatabase::Delete(KTestDbName);
1.496 + TEST2(err, KErrNotFound);
1.497 + }
1.498 + }
1.499 +
1.500 +/**
1.501 +@SYMTestCaseID SYSLIB-SQL-UT-3462
1.502 +@SYMTestCaseDesc Test for DEF105434 "SQL, persistent file I/O simulation, COMMIT problem".
1.503 + The test creates a test database with one table, inserts one record.
1.504 + Then the test attempts to retrieve the existing record while simulating file I/O failures.
1.505 + After each iteration, the database content is tested, that it has not been modified by the operation.
1.506 +@SYMTestPriority High
1.507 +@SYMTestActions Test for DEF105434 "SQL, persistent file I/O simulation, COMMIT problem".
1.508 +@SYMTestExpectedResults The test must not fail
1.509 +@SYMDEF DEF105434
1.510 +*/
1.511 +void SelectRecordTest()
1.512 + {
1.513 + (void)RSqlDatabase::Delete(KTestDbName);
1.514 + TInt err = TheDb.Create(KTestDbName);
1.515 + TEST2(err, KErrNone);
1.516 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER, Name TEXT)"));
1.517 + TEST(err >= 0);
1.518 + err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
1.519 + TEST2(err, 1);
1.520 + TheDb.Close();
1.521 + err = -1;
1.522 + for(TInt cnt=0;err<KErrNone;++cnt)
1.523 + {
1.524 + TheTest.Printf(_L("%d \r"), cnt);
1.525 + err = TheDb.Open(KTestDbName);
1.526 + TEST2(err, KErrNone);
1.527 + RSqlStatement stmt;
1.528 + (void)TheFs.SetErrorCondition(KErrGeneral, cnt);
1.529 + err = stmt.Prepare(TheDb, _L("SELECT * FROM A WHERE Id=?"));
1.530 + if(err == KErrNone)
1.531 + {
1.532 + err = stmt.BindInt(0, 1);
1.533 + if(err == KErrNone)
1.534 + {
1.535 + err = stmt.Next();
1.536 + TEST(err == KSqlAtRow || err < 0);
1.537 + if(err == KSqlAtRow)
1.538 + {
1.539 + TInt id = stmt.ColumnInt(0);
1.540 + TEST2(id, 1);
1.541 + TPtrC name;
1.542 + err = stmt.ColumnText(1, name);
1.543 + TEST2(err, KErrNone);
1.544 + TEST(name == _L("Name"));
1.545 + }
1.546 + }
1.547 + }
1.548 + (void)TheFs.SetErrorCondition(KErrNone);
1.549 + stmt.Close();
1.550 + TheDb.Close();
1.551 + //check the database content is the same as before the operation
1.552 + TEST(CheckRecord(KTestDbName, 1, _L("Name")));
1.553 + }
1.554 + (void)TheFs.SetErrorCondition(KErrNone);
1.555 + TEST(err >= 0);
1.556 + TheDb.Close();
1.557 + //check the database content is the same as before the operation, after reopening the database.
1.558 + TEST(CheckRecord(KTestDbName, 1, _L("Name")));
1.559 + err = RSqlDatabase::Delete(KTestDbName);
1.560 + TEST2(err, KErrNone);
1.561 + TheTest.Printf(_L("\r\n"));
1.562 + }
1.563 +
1.564 +/**
1.565 +@SYMTestCaseID SYSLIB-SQL-UT-3463
1.566 +@SYMTestCaseDesc Test for DEF105434 "SQL, persistent file I/O simulation, COMMIT problem".
1.567 + The test creates a test database with one table, inserts one record.
1.568 + Then the test attempts to insert another while simulating file I/O failures.
1.569 + After each iteration, the database content is tested, that it has not been modified by the operation.
1.570 + If the operation succeeds, the database content is tested again to check that the inserted record is there.
1.571 +@SYMTestPriority High
1.572 +@SYMTestActions Test for DEF105434 "SQL, persistent file I/O simulation, COMMIT problem".
1.573 +@SYMTestExpectedResults The test must not fail
1.574 +@SYMDEF DEF105434
1.575 +*/
1.576 +void InsertRecordTest()
1.577 + {
1.578 + (void)RSqlDatabase::Delete(KTestDbName);
1.579 + TInt err = TheDb.Create(KTestDbName);
1.580 + TEST2(err, KErrNone);
1.581 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Name TEXT)"));
1.582 + TEST(err >= 0);
1.583 + err = TheDb.Exec(_L("INSERT INTO A(Id,Name) VALUES(1,'Name')"));
1.584 + TEST2(err, 1);
1.585 + TheDb.Close();
1.586 + err = -1;
1.587 + for(TInt cnt=0;err<KErrNone;++cnt)
1.588 + {
1.589 + TheTest.Printf(_L("%d \r"), cnt);
1.590 + err = TheDb.Open(KTestDbName);
1.591 + TEST2(err, KErrNone);
1.592 + RSqlStatement stmt;
1.593 + (void)TheFs.SetErrorCondition(KErrGeneral, cnt);
1.594 + err = stmt.Prepare(TheDb, _L("INSERT INTO A(Id,Name) VALUES(2, 'Name2')"));
1.595 + if(err == KErrNone)
1.596 + {
1.597 + err = TheDb.Exec(_L("BEGIN TRANSACTION"));
1.598 + if(err == KErrNone)
1.599 + {
1.600 + err = stmt.Exec();
1.601 + TEST(err == 1 || err < 0);
1.602 + if(err == 1)
1.603 + {
1.604 + err = TheDb.Exec(_L("COMMIT TRANSACTION"));
1.605 + }
1.606 + }
1.607 + }
1.608 + (void)TheFs.SetErrorCondition(KErrNone);
1.609 + stmt.Close();
1.610 + if(err < 1)
1.611 + {
1.612 + TheDb.Close();//close the database to recover from the last error
1.613 + //check that the database contains the "name" record that has been inserted before the file I/O failure test.
1.614 + TEST(CheckRecord(KTestDbName, 1, _L("Name")));
1.615 + }
1.616 + else
1.617 + {
1.618 + TEST2(err, 1);
1.619 + //check the database content has been modified by the operation, without closing the database.
1.620 + TEST(CheckRecord(KTestDbName, 1, _L("Name"), EFalse));
1.621 + TEST(CheckRecord(KTestDbName, 2, _L("Name2"), EFalse));
1.622 + TheDb.Close();
1.623 + }
1.624 + }
1.625 + (void)TheFs.SetErrorCondition(KErrNone);
1.626 + TEST2(err, 1);
1.627 + //check the database content (transaction durability).
1.628 + TEST(CheckRecord(KTestDbName, 1, _L("Name")));
1.629 + TEST(CheckRecord(KTestDbName, 2, _L("Name2")));
1.630 + (void)RSqlDatabase::Delete(KTestDbName);
1.631 + TheTest.Printf(_L("\r\n"));
1.632 + }
1.633 +
1.634 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.635 +////////////////////////////////// Removable media robustness test /////////////////////////////////////////
1.636 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.637 +
1.638 +_LIT8(KNameColData, "A123456789012345678901234567890");
1.639 +_LIT8(KUpdatedNameColData, "1234");
1.640 +
1.641 +//TRemovableMediaTest class is used for testing the SQLITE behaviour when the database file is created on a removable media where
1.642 +//the cluster size is bigger than the page size and in case of a power failure is not guaranteed that the content
1.643 +//of the last updated cluster will be preserved.
1.644 +class TRemovableMediaTest
1.645 + {
1.646 + enum {KTestRecCnt = 200};
1.647 + enum {KMinCachePageSize = 512};
1.648 +
1.649 +public:
1.650 + void Run();
1.651 +
1.652 +private:
1.653 + TInt GetRemovableMediaDriveNo();
1.654 + TInt ClusterSize(TInt aDriveNo);
1.655 + void CreateDatabase(TInt aDriveNo, TInt aCachePageSize);
1.656 + void CheckRecord(sqlite3_stmt* aStmt, TInt aRecId);
1.657 + void VerifyDatabase();
1.658 + void DoTest();
1.659 +
1.660 + };
1.661 +
1.662 +//Returns the number of the removable media drive, KErrNotFound otherwise.
1.663 +TInt TRemovableMediaTest::GetRemovableMediaDriveNo()
1.664 + {
1.665 + for(TInt driveNo=EDriveA;driveNo<=EDriveZ;++driveNo)
1.666 + {
1.667 + TDriveInfo driveInfo;
1.668 + TInt err = TheFs.Drive(driveInfo, driveNo);
1.669 + if(err == KErrNone)
1.670 + {
1.671 + _LIT(KType1, "Not present");
1.672 + _LIT(KType2, "Unknown");
1.673 + _LIT(KType3, "Floppy");
1.674 + _LIT(KType4, "Hard disk");
1.675 + _LIT(KType5, "CD ROM");
1.676 + _LIT(KType6, "RAM disk");
1.677 + _LIT(KType7, "Flash");
1.678 + _LIT(KType8, "ROM drive");
1.679 + _LIT(KType9, "Remote drive");
1.680 + _LIT(KType10,"NAND flash");
1.681 + _LIT(KType11,"Rotating media");
1.682 + _LIT(KYes, "Yes");
1.683 + _LIT(KNo, "No ");
1.684 + TPtrC KMediaTypeNames[] = {KType1(), KType2(), KType3(), KType4(), KType5(), KType6(), KType7(), KType8(), KType9(), KType10(), KType11()};
1.685 + TheTest.Printf(_L("Drive: %C:, %S, Removable: %S\r\n"), 'A' + driveNo, &KMediaTypeNames[driveInfo.iType],
1.686 + driveInfo.iDriveAtt & KDriveAttRemovable ? &KYes : &KNo);
1.687 + if(driveInfo.iDriveAtt & KDriveAttRemovable)
1.688 + {
1.689 + TheTest.Printf(_L("Removable drive to test: %C:\r\n"), 'A' + driveNo);
1.690 + return driveNo;
1.691 + }
1.692 + }
1.693 + }
1.694 + return KErrNotFound;
1.695 + }
1.696 +
1.697 +//Get the cluster size of aDriveNo drive
1.698 +TInt TRemovableMediaTest::ClusterSize(TInt aDriveNo)
1.699 + {
1.700 + __ASSERT_DEBUG((TUint)aDriveNo <= EDriveZ, User::Invariant());
1.701 + TVolumeIOParamInfo volIoParams;
1.702 + TInt err = TheFs.VolumeIOParam(aDriveNo, volIoParams);
1.703 + return (err == KErrNone) ? volIoParams.iClusterSize : err;
1.704 + }
1.705 +
1.706 +//Create a test database on aDriveNo with aCachePageSize page size.
1.707 +//Insert KTestRecCnt records.
1.708 +void TRemovableMediaTest::CreateDatabase(TInt aDriveNo, TInt aCachePageSize)
1.709 + {
1.710 + __ASSERT_DEBUG((TUint)aDriveNo <= EDriveZ, User::Invariant());
1.711 + __ASSERT_DEBUG(aCachePageSize > 0, User::Invariant());
1.712 + TDriveUnit drvUnit(aDriveNo);
1.713 + _LIT(KDbName, "\\flashmedia.db");
1.714 + TParse parse;
1.715 + parse.Set(drvUnit.Name(), &KDbName, 0);
1.716 + TheRmvMediaDbFileName.Copy(parse.FullName());
1.717 + TBuf8<KMaxFileName + 1> dbFileName8;
1.718 + dbFileName8.Copy(TheRmvMediaDbFileName);
1.719 + (void)TheFs.Delete(TheRmvMediaDbFileName);
1.720 +
1.721 + sqlite3* dbHandle = NULL;
1.722 + TInt rc = sqlite3_open((const char*)dbFileName8.PtrZ(), &dbHandle);
1.723 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.724 + __ASSERT_DEBUG(dbHandle != NULL, User::Invariant());
1.725 +
1.726 + TBuf8<40> config;
1.727 + config.Copy(_L8("PRAGMA PAGE_SIZE="));
1.728 + config.AppendNum(aCachePageSize);
1.729 + rc = sqlite3_exec(dbHandle, (const char*)config.PtrZ(), 0, 0, 0);
1.730 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.731 +
1.732 + rc = sqlite3_exec(dbHandle, "CREATE TABLE A(Id INTEGER,Name TEXT)", 0, 0, 0);
1.733 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.734 + rc = sqlite3_exec(dbHandle, "BEGIN", 0, 0, 0);
1.735 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.736 + for(TInt recid=1;recid<=KTestRecCnt;++recid)
1.737 + {
1.738 +
1.739 + TBuf8<100> sql;
1.740 + sql.Copy(_L8("INSERT INTO A VALUES("));
1.741 + sql.AppendNum(recid);
1.742 + sql.Append(_L8(",'"));
1.743 + sql.Append(KNameColData);
1.744 + sql.Append(_L8("')"));
1.745 + rc = sqlite3_exec(dbHandle, (const char*)sql.PtrZ(), 0, 0, 0);
1.746 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.747 + }
1.748 + rc = sqlite3_exec(dbHandle, "COMMIT", 0, 0, 0);
1.749 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.750 + sqlite3_close(dbHandle);
1.751 + }
1.752 +
1.753 +//Checks the content of a single record
1.754 +void TRemovableMediaTest::CheckRecord(sqlite3_stmt* aStmt, TInt aRecId)
1.755 + {
1.756 + __ASSERT_DEBUG(aStmt != NULL, User::Invariant());
1.757 + TInt id = sqlite3_column_int(aStmt, 0);
1.758 + TEST2(id, aRecId);
1.759 + const TUint8* text = (const TUint8*)sqlite3_column_text(aStmt, 1);
1.760 + TPtrC8 name(text, User::StringLength(text));
1.761 + TEST(KNameColData() == name || KUpdatedNameColData() == name);
1.762 + }
1.763 +
1.764 +//Verifies that the database content is either the same as it was before the UPDATE operation or
1.765 +//it has been updated with the new data.
1.766 +void TRemovableMediaTest::VerifyDatabase()
1.767 + {
1.768 + TBuf8<KMaxFileName + 1> dbFileName8;
1.769 + dbFileName8.Copy(TheRmvMediaDbFileName);
1.770 +
1.771 + sqlite3* dbHandle = NULL;
1.772 + TInt rc = sqlite3_open((const char*)dbFileName8.PtrZ(), &dbHandle);
1.773 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.774 + __ASSERT_DEBUG(dbHandle != NULL, User::Invariant());
1.775 +
1.776 + sqlite3_stmt* stmtHandle = NULL;
1.777 + rc = sqlite3_prepare(dbHandle, "SELECT Id,Name FROM A", -1, &stmtHandle, 0);
1.778 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.779 + __ASSERT_DEBUG(stmtHandle != NULL, User::Invariant());
1.780 +
1.781 + for(TInt recid=1;recid<=KTestRecCnt;++recid)
1.782 + {
1.783 + rc = sqlite3_step(stmtHandle);
1.784 + SQLITE_TEST(dbHandle, rc, SQLITE_ROW);
1.785 + CheckRecord(stmtHandle, recid);
1.786 + }
1.787 + rc = sqlite3_step(stmtHandle);
1.788 + SQLITE_TEST(dbHandle, rc, SQLITE_DONE);
1.789 +
1.790 + sqlite3_finalize(stmtHandle);
1.791 + sqlite3_close(dbHandle);
1.792 + }
1.793 +
1.794 +//Simulates a file system error in a loop.
1.795 +//Attempts to update single record in a transaction.
1.796 +//If the UPDATE operation fails - verifies the database content on each iteration.
1.797 +//Note: pages are stored at the moment, not clusters. The database operations are not more robust if
1.798 +// clusters are stored in a case of a removable media.
1.799 +void TRemovableMediaTest::DoTest()
1.800 + {
1.801 + TheTest.Printf(_L("Update 1 record in a file I/o simulation loop\r\n"));
1.802 + TInt rc = -1;
1.803 + TBuf8<KMaxFileName + 1> dbFileName8;
1.804 + dbFileName8.Copy(TheRmvMediaDbFileName);
1.805 + for(TInt cnt=0;rc!=SQLITE_OK;++cnt)
1.806 + {
1.807 + TheTest.Printf(_L("%d \r"), cnt);
1.808 + sqlite3* dbHandle = NULL;
1.809 + rc = sqlite3_open((const char*)dbFileName8.PtrZ(), &dbHandle);
1.810 + SQLITE_TEST(dbHandle, rc, SQLITE_OK);
1.811 + __ASSERT_DEBUG(dbHandle != NULL, User::Invariant());
1.812 + (void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
1.813 + rc = sqlite3_exec(dbHandle, "BEGIN IMMEDIATE", 0, 0, 0);
1.814 + if(rc == SQLITE_OK)
1.815 + {
1.816 + rc = sqlite3_exec(dbHandle, "UPDATE A SET Name='1234' WHERE Id=1", 0, 0, 0);
1.817 + if(rc == SQLITE_OK)
1.818 + {
1.819 + TInt cnt = sqlite3_changes(dbHandle);
1.820 + TEST2(cnt, 1);
1.821 + rc = sqlite3_exec(dbHandle, "COMMIT", 0, 0, 0);
1.822 + }
1.823 + }
1.824 + (void)TheFs.SetErrorCondition(KErrNone);
1.825 + sqlite3_close(dbHandle);
1.826 + if(rc != SQLITE_OK)
1.827 + {
1.828 + VerifyDatabase();
1.829 + }
1.830 + }
1.831 + TEST2(rc, SQLITE_OK);
1.832 + VerifyDatabase();
1.833 + }
1.834 +
1.835 +void TRemovableMediaTest::Run()
1.836 + {
1.837 + TInt driveNo = GetRemovableMediaDriveNo();
1.838 + if(driveNo == KErrNotFound)
1.839 + {
1.840 + TheTest.Printf(_L("No removable media discovered. Test case not executed.\r\n"));
1.841 + return;
1.842 + }
1.843 + TInt clusterSize = ClusterSize(driveNo);
1.844 + if(clusterSize < 0)
1.845 + {
1.846 + TheTest.Printf(_L("Error %d retrieving the cluster size of drive %C. Test case not executed.\r\n"), clusterSize, 'A' + driveNo);
1.847 + return;
1.848 + }
1.849 + if(clusterSize <= KMinCachePageSize)
1.850 + {
1.851 + TheTest.Printf(_L("Cluster size: %d. No appropriate cache page size found. Test case not executed.\r\n"), clusterSize);
1.852 + return;
1.853 + }
1.854 +
1.855 + TheTest.Printf(_L("Cluster size: %d. Cache page size %d.\r\nBegin test.\r\n"), clusterSize, KMinCachePageSize);
1.856 + CreateDatabase(driveNo, KMinCachePageSize);
1.857 + DoTest();
1.858 + (void)TheFs.Delete(TheRmvMediaDbFileName);
1.859 + TheTest.Printf(_L("End test.\r\n"));
1.860 + }
1.861 +
1.862 +/**
1.863 +@SYMTestCaseID SYSLIB-SQL-UT-3516
1.864 +@SYMTestCaseDesc Removable media robustness test
1.865 + The test creates a test database with a table with some records. Then the test verifies
1.866 + that the database content cannot be corrupted by file I/O failures during database updates,
1.867 + when the database file is on a removable media and the media cluster size is bigger than the
1.868 + database page size.
1.869 +@SYMTestPriority High
1.870 +@SYMTestActions Removable media robustness test
1.871 +@SYMTestExpectedResults The test must not fail
1.872 +@SYMREQ REQ7913
1.873 +*/
1.874 +void RemovableMediaRobustnessTest()
1.875 + {
1.876 + TRemovableMediaTest removableMediaTest;
1.877 + removableMediaTest.Run();
1.878 + }
1.879 +
1.880 +/**
1.881 +@SYMTestCaseID SYSLIB-SQL-UT-4044
1.882 +@SYMTestCaseDesc RSqlDatabase::Size(TSize&), file I/O error simulation test.
1.883 + The test creates a database and executes RSqldatabase::Size(TSize&)
1.884 + during a file I/O error simulation. The database should not be corrupted
1.885 + by the call.
1.886 +@SYMTestPriority High
1.887 +@SYMTestActions RSqlDatabase::Size(TSize&), file I/O error simulation test.
1.888 +@SYMTestExpectedResults Test must not fail
1.889 +@SYMREQ REQ10407
1.890 +*/
1.891 +void SizeTest()
1.892 + {
1.893 + (void)RSqlDatabase::Delete(KTestDbName);
1.894 + TInt err = TheDb.Create(KTestDbName);
1.895 + TEST2(err, KErrNone);
1.896 + err = TheDb.Exec(_L("BEGIN;CREATE TABLE A(Id INTEGER,Data BLOB);INSERT INTO A VALUES(1, x'11223344');COMMIT;"));
1.897 + TEST(err >= 0);
1.898 + RSqlDatabase::TSize size1 = {-1, -1};
1.899 + err = TheDb.Size(size1);
1.900 + TEST2(err, KErrNone);
1.901 + TEST(size1.iSize > 0);
1.902 + TEST2(size1.iFree, 0);
1.903 + TheDb.Close();
1.904 + //"File I/O" error simulation loop
1.905 + err = KErrCorrupt;
1.906 + for(TInt cnt=0;err<KErrNone;++cnt)
1.907 + {
1.908 + TheTest.Printf(_L("%d \r"), cnt);
1.909 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.910 + (void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
1.911 + RSqlDatabase::TSize size2 = {-1, -1};
1.912 + err = TheDb.Size(size2);
1.913 + (void)TheFs.SetErrorCondition(KErrNone);
1.914 + TheDb.Close();
1.915 + if(err == KErrNone)
1.916 + {
1.917 + TEST(size2.iSize == size1.iSize);
1.918 + TEST(size2.iFree == size1.iFree);
1.919 + break;
1.920 + }
1.921 + else
1.922 + {
1.923 + //check the database content - all bets are off in a case of an I/O error.
1.924 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.925 + TSqlScalarFullSelectQuery q(TheDb);
1.926 + TInt recCnt = 0;
1.927 + TRAPD(err2, recCnt = q.SelectIntL(_L8("SELECT COUNT(*) FROM A")));
1.928 + TheDb.Close();
1.929 + TEST2(err2, KErrNone);
1.930 + TEST2(recCnt, 1);
1.931 + }
1.932 + }
1.933 + (void)RSqlDatabase::Delete(KTestDbName);
1.934 + }
1.935 +
1.936 +/**
1.937 +@SYMTestCaseID SYSLIB-SQL-UT-4045
1.938 +@SYMTestCaseDesc RSqlDatabase::Compact(), file I/O error simulation test.
1.939 + The test creates a database and executes RSqlDatabase::Compact()
1.940 + during a file I/O error simulation. The database should not be corrupted
1.941 + by the call.
1.942 +@SYMTestPriority High
1.943 +@SYMTestActions RSqlDatabase::Compact(), file I/O error simulation test.
1.944 +@SYMTestExpectedResults Test must not fail
1.945 +@SYMREQ REQ10405
1.946 +*/
1.947 +void CompactTest()
1.948 + {
1.949 + (void)RSqlDatabase::Delete(KTestDbName);
1.950 + _LIT8(KConfig, "compaction=manual");
1.951 + TInt err = TheDb.Create(KTestDbName, &KConfig);
1.952 + TEST2(err, KErrNone);
1.953 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Data BLOB)"));
1.954 + TEST(err >= 0);
1.955 + //Insert records
1.956 + err = TheDb.Exec(_L8("BEGIN"));
1.957 + TEST(err >= 0);
1.958 + const TInt KRecLen = 1000;
1.959 + TBuf8<KRecLen> sqlfmt;
1.960 + sqlfmt.Copy(_L8("INSERT INTO A VALUES(%d,x'"));
1.961 + for(TInt j=0;j<(KRecLen-50);++j)
1.962 + {
1.963 + sqlfmt.Append(_L8("A"));
1.964 + }
1.965 + sqlfmt.Append(_L8("')"));
1.966 + const TInt KRecCount = 100;
1.967 + for(TInt i=0;i<KRecCount;++i)
1.968 + {
1.969 + TBuf8<KRecLen> sql;
1.970 + sql.Format(sqlfmt, i + 1);
1.971 + err = TheDb.Exec(sql);
1.972 + TEST2(err, 1);
1.973 + }
1.974 + err = TheDb.Exec(_L8("COMMIT"));
1.975 + TEST(err >= 0);
1.976 + //Free some space
1.977 + const TInt KDeletedRecCnt = KRecCount - 10;
1.978 + err = TheDb.Exec(_L8("DELETE FROM A WHERE Id > 10"));
1.979 + TEST(err >= 0);
1.980 + //Get the database size
1.981 + RSqlDatabase::TSize size;
1.982 + err = TheDb.Size(size);
1.983 + TEST2(err, KErrNone);
1.984 + TheDb.Close();
1.985 + TEST(size.iSize > 0);
1.986 + TEST(size.iFree > 0);
1.987 + //"File I/O" error simulation loop
1.988 + err = KErrCorrupt;
1.989 + for(TInt cnt=0;err<KErrNone;++cnt)
1.990 + {
1.991 + TheTest.Printf(_L("%d \r"), cnt);
1.992 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.993 + (void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
1.994 + err = TheDb.Compact(RSqlDatabase::EMaxCompaction);
1.995 + (void)TheFs.SetErrorCondition(KErrNone);
1.996 + TheDb.Close();
1.997 + if(err == KErrNone)
1.998 + {
1.999 + break;
1.1000 + }
1.1001 + else
1.1002 + {
1.1003 + //check the database content - all bets are off in a case of an I/O error.
1.1004 + //The database maight have been compacted, so - no check for that.
1.1005 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.1006 + TSqlScalarFullSelectQuery q(TheDb);
1.1007 + TInt recCnt = 0;
1.1008 + TRAPD(err2, recCnt = q.SelectIntL(_L8("SELECT COUNT(*) FROM A")));
1.1009 + TheDb.Close();
1.1010 + TEST2(err2, KErrNone);
1.1011 + TEST2(recCnt, (KRecCount - KDeletedRecCnt));
1.1012 + }
1.1013 + }
1.1014 + TheTest.Printf(_L("\r\n"));
1.1015 + //Check that the database has been really compacted
1.1016 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.1017 + RSqlDatabase::TSize size2;
1.1018 + err = TheDb.Size(size2);
1.1019 + TEST2(err, KErrNone);
1.1020 + TheDb.Close();
1.1021 + (void)RSqlDatabase::Delete(KTestDbName);
1.1022 + TEST(size.iSize > size2.iSize);
1.1023 + TEST2(size2.iFree, 0);
1.1024 + }
1.1025 +
1.1026 +void DoBlobWriteStreamTestL(TBool aAttachDb)
1.1027 + {
1.1028 + RSqlBlobWriteStream strm;
1.1029 + CleanupClosePushL(strm);
1.1030 + if(aAttachDb)
1.1031 + {
1.1032 + strm.OpenL(TheDb, _L("A"), _L("Data"), 1, KAttachDb);
1.1033 + }
1.1034 + else
1.1035 + {
1.1036 + strm.OpenL(TheDb, _L("A"), _L("Data"), 1);
1.1037 + }
1.1038 +
1.1039 + TBuf8<KBlobSize / KWriteCnt> data;
1.1040 + data.SetLength(KBlobSize / KWriteCnt);
1.1041 + data.Fill(0xA5);
1.1042 +
1.1043 + for(TInt i=0;i<KWriteCnt;++i)
1.1044 + {
1.1045 + strm.WriteL(data);
1.1046 + }
1.1047 +
1.1048 + strm.CommitL();
1.1049 +
1.1050 + CleanupStack::PopAndDestroy(&strm);
1.1051 + }
1.1052 +
1.1053 +/**
1.1054 +@SYMTestCaseID SYSLIB-SQL-UT-4089
1.1055 +@SYMTestCaseDesc RSqlBlobWriteStream::WriteL(), file I/O error simulation test.
1.1056 + The test creates a database and executes RSqlBlobWriteStream::WriteL()
1.1057 + during a file I/O error simulation. The database should not be corrupted
1.1058 + by the call.
1.1059 +@SYMTestPriority High
1.1060 +@SYMTestActions RSqlBlobWriteStream::WriteL(), file I/O error simulation test.
1.1061 +@SYMTestExpectedResults Test must not fail
1.1062 +@SYMREQ REQ5792
1.1063 + REQ10418
1.1064 +*/
1.1065 +void BlobWriteStreamTest(TBool aAttachDb)
1.1066 + {
1.1067 + (void)RSqlDatabase::Delete(KTestDbName);
1.1068 + TInt err = TheDb.Create(KTestDbName);
1.1069 + TEST2(err, KErrNone);
1.1070 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Data BLOB)"));
1.1071 + TEST2(err, 1);
1.1072 + TBuf8<100> sql;
1.1073 + sql.Format(_L8("INSERT INTO A VALUES(1, zeroblob(%d))"), KBlobSize);
1.1074 + err = TheDb.Exec(sql);
1.1075 + TEST2(err, 1);
1.1076 + TheDb.Close();
1.1077 +
1.1078 + err = KErrCorrupt;
1.1079 + for(TInt cnt=0;err<KErrNone;++cnt)
1.1080 + {
1.1081 + TheTest.Printf(_L("%d \r"), cnt);
1.1082 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.1083 + if(aAttachDb)
1.1084 + {
1.1085 + TEST2(TheDb.Attach(KTestDbName, KAttachDb), KErrNone);
1.1086 + }
1.1087 + (void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
1.1088 + TRAP(err, DoBlobWriteStreamTestL(aAttachDb));
1.1089 + (void)TheFs.SetErrorCondition(KErrNone);
1.1090 + if(aAttachDb)
1.1091 + {
1.1092 + TEST2(TheDb.Detach(KAttachDb), KErrNone);
1.1093 + }
1.1094 + TheDb.Close();
1.1095 + }
1.1096 + TheTest.Printf(_L("\r\n"));
1.1097 +
1.1098 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.1099 +
1.1100 + RSqlStatement stmt;
1.1101 + err = stmt.Prepare(TheDb, _L8("SELECT * FROM A"));
1.1102 + TEST2(err, KErrNone);
1.1103 + err = stmt.Next();
1.1104 + TEST2(err, KSqlAtRow);
1.1105 + TPtrC8 data;
1.1106 + err = stmt.ColumnBinary(1, data);
1.1107 + TEST2(err, KErrNone);
1.1108 + TEST2(data.Length(), KBlobSize);
1.1109 + for(TInt j=0;j<KBlobSize;++j)
1.1110 + {
1.1111 + TUint8 d = data[j];
1.1112 + TEST2(d, 0xA5);
1.1113 + }
1.1114 + stmt.Close();
1.1115 +
1.1116 + TheDb.Close();
1.1117 + (void)RSqlDatabase::Delete(KTestDbName);
1.1118 + }
1.1119 +
1.1120 +void DoBlobReadStreamTestL(TBool aAttachDb, TDes8& aDes)
1.1121 + {
1.1122 + RSqlBlobReadStream strm;
1.1123 + CleanupClosePushL(strm);
1.1124 + if(aAttachDb)
1.1125 + {
1.1126 + strm.OpenL(TheDb, _L("A"), _L("Data"), 1, KAttachDb);
1.1127 + }
1.1128 + else
1.1129 + {
1.1130 + strm.OpenL(TheDb, _L("A"), _L("Data"), 1);
1.1131 + }
1.1132 +
1.1133 + TBuf8<KBlobSize / KWriteCnt> data;
1.1134 + aDes.SetLength(0);
1.1135 +
1.1136 + for(TInt i=0;i<KWriteCnt;++i)
1.1137 + {
1.1138 + strm.ReadL(data);
1.1139 + aDes.Append(data);
1.1140 + }
1.1141 +
1.1142 + CleanupStack::PopAndDestroy(&strm);
1.1143 + }
1.1144 +
1.1145 +/**
1.1146 +@SYMTestCaseID SYSLIB-SQL-UT-4090
1.1147 +@SYMTestCaseDesc RSqlBlobReadStream::ReadL(), file I/O error simulation test.
1.1148 + The test creates a database and executes RSqlBlobReadStream::ReadL()
1.1149 + during a file I/O error simulation. The database should not be corrupted
1.1150 + by the call.
1.1151 +@SYMTestPriority High
1.1152 +@SYMTestActions RSqlBlobReadStream::ReadL(), file I/O error simulation test.
1.1153 +@SYMTestExpectedResults Test must not fail
1.1154 +@SYMREQ REQ5792
1.1155 + REQ10410
1.1156 + REQ10411
1.1157 +*/
1.1158 +void BlobReadStreamTest(TBool aAttachDb)
1.1159 + {
1.1160 + (void)RSqlDatabase::Delete(KTestDbName);
1.1161 + TInt err = TheDb.Create(KTestDbName);
1.1162 + TEST2(err, KErrNone);
1.1163 + err = TheDb.Exec(_L("CREATE TABLE A(Id INTEGER,Data BLOB)"));
1.1164 + TEST2(err, 1);
1.1165 + TBuf8<100> sql;
1.1166 + sql.Format(_L8("INSERT INTO A VALUES(1, zeroblob(%d))"), KBlobSize);
1.1167 + err = TheDb.Exec(sql);
1.1168 + TEST2(err, 1);
1.1169 + TRAP(err, DoBlobWriteStreamTestL(EFalse));
1.1170 + TEST2(err, KErrNone);
1.1171 + TheDb.Close();
1.1172 +
1.1173 + HBufC8* buf = HBufC8::New(KBlobSize);
1.1174 + TEST(buf != NULL);
1.1175 + TPtr8 bufptr = buf->Des();
1.1176 +
1.1177 + err = KErrCorrupt;
1.1178 + for(TInt cnt=0;err<KErrNone;++cnt)
1.1179 + {
1.1180 + TheTest.Printf(_L("%d \r"), cnt);
1.1181 + TEST2(TheDb.Open(KTestDbName), KErrNone);
1.1182 + if(aAttachDb)
1.1183 + {
1.1184 + TEST2(TheDb.Attach(KTestDbName, KAttachDb), KErrNone);
1.1185 + }
1.1186 + (void)TheFs.SetErrorCondition(KErrCorrupt, cnt);
1.1187 + TRAP(err, DoBlobReadStreamTestL(aAttachDb, bufptr));
1.1188 + (void)TheFs.SetErrorCondition(KErrNone);
1.1189 + if(aAttachDb)
1.1190 + {
1.1191 + TEST2(TheDb.Detach(KAttachDb), KErrNone);
1.1192 + }
1.1193 + TheDb.Close();
1.1194 + }
1.1195 + TheTest.Printf(_L("\r\n"));
1.1196 +
1.1197 + TEST2(bufptr.Length(), KBlobSize);
1.1198 + for(TInt j=0;j<KBlobSize;++j)
1.1199 + {
1.1200 + TUint8 d = bufptr[j];
1.1201 + TEST2(d, 0xA5);
1.1202 + }
1.1203 +
1.1204 + delete buf;
1.1205 +
1.1206 + (void)RSqlDatabase::Delete(KTestDbName);
1.1207 + }
1.1208 +
1.1209 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.1210 +
1.1211 +void DoTests()
1.1212 + {
1.1213 + TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3419 Alter database during file I/O error "));
1.1214 + AlterDatabaseTest();
1.1215 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3420 Alter database during file I/O error (using statement object) "));
1.1216 + AlterDatabaseTest2();
1.1217 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3421 Open database during file I/O error "));
1.1218 + OpenDatabaseTest();
1.1219 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3434 Create database during file I/O error "));
1.1220 + CreateDatabaseTest();
1.1221 + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4189 Attach database during file I/O error "));
1.1222 + AttachDatabaseTest();
1.1223 + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4190 Delete database during file I/O error "));
1.1224 + DeleteDatabaseTest();
1.1225 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3462 Select record test during file I/O error "));
1.1226 + SelectRecordTest();
1.1227 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3463 Insert record test during file I/O error "));
1.1228 + InsertRecordTest();
1.1229 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-3516 Removable Media robustness test "));
1.1230 + RemovableMediaRobustnessTest();
1.1231 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4044 Database size test during file I/O error"));
1.1232 + SizeTest();
1.1233 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4045 Compact database test during file I/O error"));
1.1234 + CompactTest();
1.1235 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4089 RSqlBlobWriteStream::WriteL() test during file I/O error"));
1.1236 + BlobWriteStreamTest(EFalse);
1.1237 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4089 RSqlBlobWriteStream::WriteL()+attached database test during file I/O error"));
1.1238 + BlobWriteStreamTest(ETrue);
1.1239 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4090 RSqlBlobReadStream::ReadL() test during file I/O error"));
1.1240 + BlobReadStreamTest(EFalse);
1.1241 + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4090 RSqlBlobReadStream::ReadL()+attached database test during file I/O error"));
1.1242 + BlobReadStreamTest(ETrue);
1.1243 + }
1.1244 +
1.1245 +TInt E32Main()
1.1246 + {
1.1247 + TheTest.Title();
1.1248 +
1.1249 + CTrapCleanup* tc = CTrapCleanup::New();
1.1250 +
1.1251 + __UHEAP_MARK;
1.1252 +
1.1253 + SetupTestEnv();
1.1254 + DoTests();
1.1255 + DestroyTestEnv();
1.1256 +
1.1257 + __UHEAP_MARKEND;
1.1258 +
1.1259 + TheTest.End();
1.1260 + TheTest.Close();
1.1261 +
1.1262 + delete tc;
1.1263 +
1.1264 + User::Heap().Check();
1.1265 + return KErrNone;
1.1266 + }