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