// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
#include <e32test.h>
#include <bautils.h>
#include "SqlSrvMain.h"
#include "SqlSrvStartup.h"
#include "SqlSrvUtil.h"
_LIT(KCfgDb1ConfigFilePath, "c:\\private\\10281e17\\cfg[10281E17]t_sqlstartup1.db.02"); // config file version 2 for t_sqlstartup1.db
_LIT(KCfgDb2ConfigFilePath, "c:\\private\\10281e17\\cfg[10281E17]t_sqlstartup2.db.05"); // config file version 5 for t_sqlstartup2.db
//This subdir is created by t_sqlenvcreate app. It should not be returned in the list of files for backup.
_LIT(KPrivateSubDir, "c:\\private\\10281e17\\TestDir.db");
///////////////////////////////////////////////////////////////////////////////////////
RTest TheTest(_L("t_sqlstartup test"));
RFs TheFs;
static TInt TheProcessHandleCount = 0;
static TInt TheThreadHandleCount = 0;
static TInt TheAllocatedCellsCount = 0;
#ifdef _DEBUG
static const TInt KBurstRate = 20;
#endif
///////////////////////////////////////////////////////////////////////////////////////
void DeleteTestFiles()
{
(void)TheFs.Delete(KCfgDb2ConfigFilePath);
(void)TheFs.Delete(KCfgDb1ConfigFilePath);
TheFs.Close();
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
//Test macros and functions
void Check(TInt aValue, TInt aLine)
{
if(!aValue)
{
DeleteTestFiles();
RDebug::Print(_L("*** Expresssion evaluated to false\r\n"));
TheTest(EFalse, aLine);
}
}
void Check(TInt aValue, TInt aExpected, TInt aLine)
{
if(aValue != aExpected)
{
DeleteTestFiles();
RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
TheTest(EFalse, aLine);
}
}
#define TEST(arg) ::Check((arg), __LINE__)
#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void MarkHandles()
{
RThread().HandleCount(TheProcessHandleCount, TheThreadHandleCount);
}
static void MarkAllocatedCells()
{
TheAllocatedCellsCount = User::CountAllocCells();
}
static void CheckAllocatedCells()
{
TInt allocatedCellsCount = User::CountAllocCells();
TEST2(allocatedCellsCount, TheAllocatedCellsCount);
}
static void CheckHandles()
{
TInt endProcessHandleCount;
TInt endThreadHandleCount;
RThread().HandleCount(endProcessHandleCount, endThreadHandleCount);
TEST2(TheProcessHandleCount, endProcessHandleCount);
TEST2(TheThreadHandleCount, endThreadHandleCount);
}
static void OomPreStep(TInt
#ifdef _DEBUG
aFailingAllocationNo
#endif
)
{
MarkHandles();
MarkAllocatedCells();
__UHEAP_MARK;
__UHEAP_SETBURSTFAIL(RAllocator::EBurstFailNext, aFailingAllocationNo, KBurstRate);
}
static void OomPostStep()
{
__UHEAP_RESET;
__UHEAP_MARKEND;
CheckAllocatedCells();
CheckHandles();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void CreateAndDestroySqlServerL()
{
CSqlServer* server = CSqlServer::NewLC();
//Drive C: to the RSqlDriveSpaceCol object. This will allow "reserve drive space" construct/destroy code to be tested.
RSqlDriveSpaceCol& drvcol = server->DriveSpaceCol();
drvcol.AddL(EDriveC);
CleanupStack::PopAndDestroy(server);
}
static CSqlServer* CreateSqlServerL()
{
CSqlServer* server = CSqlServer::NewLC();
CleanupStack::Pop(server);
return server;
}
/**
@SYMTestCaseID PDS-SQL-UT-4159
@SYMTestCaseDesc SQL server startup OOM test
@SYMTestPriority High
@SYMTestActions Runs the SQL server startup code in an OOM loop.
@SYMTestExpectedResults Test must not fail
@SYMDEF DEF144096
*/
void SqlServerStartupOomTest()
{
TInt err = KErrNoMemory;
TInt failingAllocationNo = 0;
TheTest.Printf(_L("Iteration:\r\n"));
while(err == KErrNoMemory)
{
TheTest.Printf(_L(" %d"), ++failingAllocationNo);
OomPreStep(failingAllocationNo);
TRAP(err, CreateAndDestroySqlServerL());
OomPostStep();
}
if(err != KErrNoMemory)
{
TEST2(err, KErrNone);
}
TheTest.Printf(_L("\r\n===OOM test succeeded at heap failure rate of %d ===\r\n"), failingAllocationNo);
}
/**
@SYMTestCaseID PDS-SQL-UT-4160
@SYMTestCaseDesc CSqlServer::GetBackUpListL() OOM test
@SYMTestPriority High
@SYMTestActions Calls CSqlServer::GetBackUpListL() in an OOM loop.
@SYMTestExpectedResults Test must not fail
@SYMDEF DEF144096
*/
void GetBackupListOomTest()
{
CSqlServer* server = NULL;
TRAPD(err, server = CreateSqlServerL());
TEST2(err, KErrNone);
TInt fileCnt = 0;
err = KErrNoMemory;
TInt failingAllocationNo = 0;
TheTest.Printf(_L("Iteration:\r\n"));
while(err == KErrNoMemory)
{
TheTest.Printf(_L(" %d"), ++failingAllocationNo);
OomPreStep(failingAllocationNo);
const TUid KDbUd = {0x98765432};
RArray<TParse> files;
TRAP(err, server->GetBackUpListL(KDbUd, files));
fileCnt = files.Count();
if(err == KErrNone)
{
//No directories should be returned in the list of files for backup
for(TInt i=0;i<fileCnt;++i)
{
const TParse& parse = files[i];
TPtrC fname = parse.FullName();
TInt rc = KPrivateSubDir().CompareF(parse.FullName());
TEST(rc != 0);
}
}
files.Close();
OomPostStep();
}
delete server;
if(err != KErrNoMemory)
{
TEST2(err, KErrNone);
}
TheTest.Printf(_L("\r\n===OOM test succeeded at heap failure rate of %d ===\r\nFile count: %d\r\n"), failingAllocationNo, fileCnt);
}
/**
@SYMTestCaseID PDS-SQL-UT-4161
@SYMTestCaseDesc SQL server startup file I/O error simulation test
@SYMTestPriority High
@SYMTestActions Runs the SQL server startup code in a file I/O error simulation loop.
@SYMTestExpectedResults Test must not fail
@SYMDEF DEF144096
*/
void SqlServerStartupFileIoErrorTest()
{
RFs fs;
TInt err = fs.Connect();
TEST2(err, KErrNone);
for(TInt fsError=KErrNotFound;fsError>=KErrBadName;--fsError)
{
TheTest.Printf(_L("===Simulated error: %d\r\nIteration: "), fsError);
err = KErrNotFound;
TInt cnt=0;
while(err<KErrNone)
{
TheTest.Printf(_L("%d "), cnt);
(void)fs.SetErrorCondition(fsError, cnt);
TRAP(err, CreateAndDestroySqlServerL());
(void)fs.SetErrorCondition(KErrNone);
if(err != KErrNone)
{
++cnt;
}
}
TEST2(err, KErrNone);
TheTest.Printf(_L("\r\n===File I/O error simulation test succeeded on iteration %d===\r\n"), cnt);
}
fs.Close();
}
/**
@SYMTestCaseID PDS-SQL-UT-4162
@SYMTestCaseDesc CSqlServer::GetBackUpListL() file I/O error simulation test
@SYMTestPriority High
@SYMTestActions Calls CSqlServer::GetBackUpListL() in a file I/O error simulation loop.
@SYMTestExpectedResults Test must not fail
@SYMDEF DEF144096
*/
void GetBackupListFileIoErrorTest()
{
CSqlServer* server = NULL;
TRAPD(err, server = CreateSqlServerL());
TEST2(err, KErrNone);
for(TInt fsError=KErrNotFound;fsError>=KErrBadName;--fsError)
{
TheTest.Printf(_L("===Simulated error: %d\r\nIteration: "), fsError);
err = KErrNotFound;
TInt fileCnt = 0;
TInt cnt=0;
while(err<KErrNone)
{
TheTest.Printf(_L("%d "), cnt);
(void)server->Fs().SetErrorCondition(fsError, cnt);
const TUid KDbUd = {0x98765432};
RArray<TParse> files;
TRAP(err, server->GetBackUpListL(KDbUd, files));
fileCnt = files.Count();
if(err == KErrNone)
{
//No directories should be returned in the list of files for backup
for(TInt i=0;i<fileCnt;++i)
{
const TParse& parse = files[i];
TPtrC fname = parse.FullName();
TInt rc = KPrivateSubDir().CompareF(parse.FullName());
TEST(rc != 0);
}
}
files.Close();
(void)server->Fs().SetErrorCondition(KErrNone);
if(err != KErrNone)
{
++cnt;
}
}
TEST2(err, KErrNone);
TheTest.Printf(_L("\r\n===File I/O error simulation test succeeded on iteration %d===\r\nFile count: %d\r\n"), cnt, fileCnt);
}
delete server;
}
/**
@SYMTestCaseID PDS-SQL-UT-4163
@SYMTestCaseDesc Test for DEF144196: SQL, server code coverage can be improved
@SYMTestPriority High
@SYMTestActions Tests the UTF conversion functions implemented in SqlSrvUtil.cpp.
@SYMTestExpectedResults Test must not fail
@SYMDEF DEF144196
*/
void UtfConversionTest()
{
///////// UTF16ToUTF8() ///////////////////////
_LIT(KStr16, "abcd");
_LIT8(KStr8, "abcd");
TBuf8<KMaxFileName + 1> bufout;
TBool rc = UTF16ToUTF8(KStr16, bufout);
TEST(rc);
TEST(bufout == KStr8);
//Test where the input buffer contains non-convertible characters
TBuf<2> name2;
name2.SetLength(2);
name2[0] = TChar(0xD800);
name2[1] = TChar(0xFC00);
rc = UTF16ToUTF8(name2, bufout);
TEST(!rc);
///////// UTF16ToUTF8Z() ///////////////////////
_LIT8(KStr8Z, "abcd\x0");
rc = UTF16ToUTF8Z(KStr16, bufout);
TEST(rc);
TEST(bufout == KStr8Z);
//Test where the input buffer contains non-convertible characters
rc = UTF16ToUTF8Z(name2, bufout);
TEST(!rc);
///////// UTF16ZToUTF8Z() ///////////////////////
_LIT(KStr16Z, "abcd\x0");
rc = UTF16ZToUTF8Z(KStr16Z, bufout);
TEST(rc);
TEST(bufout == KStr8Z);
//Test where the input buffer contains non-convertible characters
TBuf<3> name3;
name3.SetLength(3);
name3[0] = TChar(0xD800);
name3[1] = TChar(0xFC00);
name3[2] = TChar(0x0000);
rc = UTF16ZToUTF8Z(name3, bufout);
TEST(!rc);
}
/**
@SYMTestCaseID PDS-SQL-UT-4175
@SYMTestCaseDesc Test for DEF144937: SQL, SQL server, the code coverage can be improved in some areas.
@SYMTestPriority High
@SYMTestActions The test creates a SQL server instance and performs some basic operations with
RSqlDriveSpaceCol object owned by the server, such as: adding a new drive,
getting an access to the reserved drive space, releasing the access.
@SYMTestExpectedResults Test must not fail
@SYMDEF DEF144937
*/
void ReserveDriveSpaceTest()
{
CSqlServer* srv = NULL;
TRAPD(err, srv = CreateSqlServerL());
TEST2(err, KErrNone);
RSqlDriveSpaceCol& drvcol = srv->DriveSpaceCol();
TRAP(err, drvcol.AddL(EDriveC));
TEST2(err, KErrNone);
CSqlDriveSpace* drvspace = drvcol.Find(EDriveZ);
TEST(!drvspace);
drvspace = drvcol.Find(EDriveC);
TEST(drvspace != NULL);
TDriveNumber drvnum = drvspace->Drive();
TEST2(drvnum, EDriveC);
//It is safe to call GetAccessL() more than once. The access is reference counted.
TRAP(err, drvspace->GetAccessL());
TEST2(err, KErrNone);
TRAP(err, drvspace->GetAccessL());
TEST2(err, KErrNone);
//It is safe if ReleaseAccess() call count do not match GetAccessL() call count.
drvspace->ReleaseAccess();
drvspace->ReleaseAccess();
drvspace->ReleaseAccess();
//
drvcol.ResetAndDestroy();
delete srv;
}
void DoCreateCfgFile(const TDesC& aFileName, const TDesC8& aData)
{
RFile file;
TInt err = file.Create(TheFs, aFileName, EFileRead | EFileWrite);
TEST2(err, KErrNone);
err = file.Write(aData);
file.Close();
TEST2(err, KErrNone);
}
void DoTests()
{
CActiveScheduler* scheduler = new CActiveScheduler;
TEST(scheduler != NULL);
CActiveScheduler::Install(scheduler);
//Adding two db config files will allow CDbConfigFiles construct/destroy code also to be tested in the OOM tests.
TInt err = TheFs.Connect();
TEST2(err, KErrNone);
DoCreateCfgFile(KCfgDb1ConfigFilePath, _L8("CREATE INDEX idx ON table1(i1);"));
DoCreateCfgFile(KCfgDb2ConfigFilePath, _L8("CREATE INDEX idx1 ON table1(i1);CREATE INDEX idx2 ON table2(i2)"));
TheTest.Start(_L(" @SYMTestCaseID:PDS-SQL-UT-4159 SQL server startup OOM test"));
SqlServerStartupOomTest();
TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-UT-4160 CSqlServer::GetBackUpListL() OOM test"));
GetBackupListOomTest();
TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-UT-4161 SQL server startup file I/O error simulation test"));
SqlServerStartupFileIoErrorTest();
TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-UT-4162 CSqlServer::GetBackUpListL() file I/O error simulation test"));
GetBackupListFileIoErrorTest();
TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-UT-4163 SQL server, UTF conversion test"));
UtfConversionTest();
TheTest.Next (_L(" @SYMTestCaseID:PDS-SQL-UT-4175 Reserve drive space tests"));
ReserveDriveSpaceTest();
delete scheduler;
}
TInt E32Main()
{
TheTest.Title();
CTrapCleanup* tc = CTrapCleanup::New();
TheTest(tc != NULL);
__UHEAP_MARK;
DoTests();
DeleteTestFiles();
__UHEAP_MARKEND;
TheTest.End();
TheTest.Close();
delete tc;
User::Heap().Check();
return KErrNone;
}