diff -r 000000000000 -r bde4ae8d615e os/persistentdata/persistentstorage/sql/TEST/t_sqlbur.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/persistentdata/persistentstorage/sql/TEST/t_sqlbur.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,1909 @@ +// Copyright (c) 2006-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 +#include +#include +#include + +#include "SqlBur.h" +#include "t_sqlbur.h" + +/////////////////////////////////////////////////////////////////////////////////////// + +RTest TheTest(_L("SQL Backup and Restore Test")); + +_LIT(KPrivateDir, "\\private\\10281e17\\"); + +//Don't forget to update DeleteBackupFiles() implementation if a new uid is added +const TSecureId KClientUid = 0x21212122; // the data owner's UID +const TSecureId KZeroFileSizeUid = 0xFFFF4321; +const TSecureId KTestClientUid1 = 0xFFFF4322; +const TSecureId KTestClientUid2 = 0xFFFF4323; +const TSecureId KTestClientUid3 = 0xFFFF4324; + +_LIT(KBackupDir, "C:\\TEST\\"); +_LIT(KBackupFileTemplate, "C:\\TEST\\Backup.bak"); +_LIT(KBackupCopy, "C:\\TEST\\Backup2.bak"); +_LIT(KBackupFile2Z, "Z:\\TEST\\t_sqlbur_backup_ver0.bak"); +_LIT(KBackupFile2, "C:\\TEST\\t_sqlbur_backup_ver0.bak"); + +_LIT(KZeroSizeFile, "C:\\private\\10281e17\\[FFFF4321]t_sqlbur_zero.db"); +_LIT(KTestFile1, "C:\\private\\10281e17\\[FFFF4322]t_sqlbur_test1.db"); +_LIT(KTestFile1NameOnly, "[FFFF4322]t_sqlbur_test1.db"); +_LIT(KTestFile1Bak, "C:\\private\\10281e17\\bak[FFFF4322]t_sqlbur_test1.db.bak"); +_LIT(KTestDeleteMask1, "C:\\private\\10281e17\\[FFFF4322]*"); +_LIT(KTestDeleteMask2, "*bur_test1.db"); +_LIT(KTestFile2, "\\private\\10281e17\\[FFFF4323]t_sqlbur_test2.db"); +_LIT(KTestFile3, "c:\\private\\10281e17\\[FFFF4324]t_sqlbur_test3.db"); +_LIT(KTestFile4, "c:\\private\\10281e17\\[FFFF4324]t_sqlbur_test4.db"); + +const TDriveNumber KTestDrive = EDriveC; + +const TUint KBufferSize = 2048; // used for reading backup files for validation + +static CActiveScheduler* TheScheduler = NULL; +static CSqlSrvTestBurInterface* TheSqlSrvTestBurInterface = NULL; + +///////////////////////////////////// + +//Test db files +_LIT(KTestDbFileName1,"C:[21212122]AADB2.db"); +_LIT(KTestDbFileName2,"C:[21212122]BBDB2.db"); + +//Temp buffers for storing files content, to be compared with what is received after the restore operation. 10 files max. +TInt TheFileCount = 0; +const TInt KMaxDbFileSize = 10 * 1024;//The max test db file size - 10 Kb max. +static TUint8 TheDbFileData[10][KMaxDbFileSize];//An array where the original db file content will be stored +static TInt TheDbFileSizes[10];//An array where the real db file size will be stored +static TUint8 TheBuf[KMaxDbFileSize]; + +///////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////// + +void DeleteBackupFiles() + { + TFileName fname; + + fname.Copy(KBackupFileTemplate); + fname.Append((static_cast (KClientUid)).Name()); + (void)TheSqlSrvTestBurInterface->Fs().Delete(fname); + + fname.Copy(KBackupFileTemplate); + fname.Append((static_cast (KZeroFileSizeUid)).Name()); + (void)TheSqlSrvTestBurInterface->Fs().Delete(fname); + + fname.Copy(KBackupFileTemplate); + fname.Append((static_cast (KTestClientUid1)).Name()); + (void)TheSqlSrvTestBurInterface->Fs().Delete(fname); + + fname.Copy(KBackupFileTemplate); + fname.Append((static_cast (KTestClientUid2)).Name()); + (void)TheSqlSrvTestBurInterface->Fs().Delete(fname); + + fname.Copy(KBackupFileTemplate); + fname.Append((static_cast (KTestClientUid3)).Name()); + (void)TheSqlSrvTestBurInterface->Fs().Delete(fname); + } + +void TestEnvDestroy() + { + (void)TheSqlSrvTestBurInterface->Fs().Delete(KBackupCopy); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1Bak); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile3); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile4); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KZeroSizeFile); + + DeleteBackupFiles(); + + delete TheSqlSrvTestBurInterface; + TheSqlSrvTestBurInterface = NULL; + + delete TheScheduler; + TheScheduler = NULL; + } + +//////////////////////////// +// Test macros and functions +//////////////////////////// + +void Check(TInt aValue, TInt aLine) + { + if(!aValue) + { + TestEnvDestroy(); + TheTest(EFalse, aLine); + } + } + +void Check(TInt aValue, TInt aExpected, TInt aLine) + { + if(aValue != aExpected) + { + TestEnvDestroy(); + 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 DestroyFileList(RArray& aFileList) + { + for(TInt i=0;iConstruct(); + return self; + } + +CSqlSrvTestBurInterface::CSqlSrvTestBurInterface() + { + } + +void CSqlSrvTestBurInterface::Construct() + { + TInt err = iFs.Connect(); + TEST2(err, KErrNone); + err = iFs.MkDir(KBackupDir); + TEST(err == KErrNone || err == KErrAlreadyExists); + err = iFs.CreatePrivatePath(KTestDrive); + TEST2(err, KErrNone); + } + +CSqlSrvTestBurInterface::~CSqlSrvTestBurInterface() + { + iFs.Close(); + } + +//Called by the backup client ot get a list of database files to backup +//The array is owned by the caller +//The SQL server would have the job to get a list of databases owned by +//the given SID and to determine whether the backup flag is set +//All databases that satisfy this requirement will be added to the array. +void CSqlSrvTestBurInterface::GetBackUpListL(TSecureId aUid, TDriveNumber aDrive, RArray& aFileList) + { + if(aUid.iId == 0) + {//Simulates that there are no databases for backup + DestroyFileList(aFileList); + return; + } + + TDriveUnit driveUnit(aDrive); + TDriveName driveName = driveUnit.Name(); + TFileName path; + path.Copy(driveName); + path.Append(KPrivateDir); + //Include the aUid and the "*" mask + TUidName uidName = (static_cast (aUid)).Name(); + _LIT(KMatchAllDbFiles, "*"); + TBuf fileNameMask(uidName); + fileNameMask.Append(KMatchAllDbFiles); + TParse parse; + TInt err = parse.Set(path, &fileNameMask, NULL); + User::LeaveIfError(err); + //Do the search + TPtrC fullPath(parse.FullName()); + CDir* fileNameCol = NULL; + err = TheSqlSrvTestBurInterface->Fs().GetDir(fullPath, KEntryAttNormal, ESortNone, fileNameCol); + if(err == KErrNotFound) + { + return; + } + User::LeaveIfError(err); + CleanupStack::PushL(fileNameCol); + TInt fileCount = fileNameCol->Count(); + err = aFileList.Reserve(fileCount); + User::LeaveIfError(err); + //Append the full database file paths to the file names list. + for(TInt i=0;i (aUid)).Name(); + _LIT(KMatchAllDbFiles, "*"); + TBuf fileNameMask(uidName); + fileNameMask.Append(KMatchAllDbFiles); + TInt err = aParse.Set(aPath, &fileNameMask, NULL); + TEST2(err, KErrNone); + } + +//Reads the content of the db files and stores the content to a global memory buffer. +//That buffer content will be used later for verification of the restore process. +void StoreDbContentToBuf(RFs& aFs, TDriveNumber aDrive, TSecureId aUid) + { + TFileName path; + PrepareSearchPath(aDrive, path); + TParse parse; + PrepareSearchPattern(path, aUid, parse); + + TheFileCount = -1; + Mem::FillZ(TheDbFileData, sizeof(TheDbFileData)); + Mem::FillZ(TheDbFileSizes, sizeof(TheDbFileSizes)); + + CDir* dir = NULL; + TInt err = aFs.GetDir(parse.FullName(), KEntryAttNormal, ESortByName, dir); + TEST2(err, KErrNone); + TheFileCount = dir->Count(); + for(TInt i=0;i 0); + + TPtr8 bufptr(TheDbFileData[i], 0, KMaxDbFileSize); + err = dbFile.Read(bufptr, fileSize); + TEST2(err, KErrNone); + TEST(fileSize == bufptr.Length()); + + TheDbFileSizes[i] = fileSize; + + dbFile.Close(); + } + delete dir; + } + +//At the moment when this function is called, the db files content is already restored. +//The function will open the restored db files and compare their content against the content +//of the original db files (kept in a global memory buffer). +void CompareDbContentWithBuf(RFs& aFs, TDriveNumber aDrive, TSecureId aUid) + { + TFileName path; + PrepareSearchPath(aDrive, path); + TParse parse; + PrepareSearchPattern(path, aUid, parse); + + CDir* dir = NULL; + TInt err = aFs.GetDir(parse.FullName(), KEntryAttNormal, ESortByName, dir); + TEST2(err, KErrNone); + TEST2(TheFileCount, dir->Count()); + for(TInt i=0;i 0); + + const ::TEntry& entry = (*dir)[i]; + err = parse.Set(path, &entry.iName, NULL); + TEST2(err, KErrNone); + TPtrC fname(parse.FullName()); + + RFile dbFile; + TInt err = dbFile.Open(aFs, fname, EFileRead); + TEST2(err, KErrNone); + + TInt fileSize = 0; + err = dbFile.Size(fileSize); + TEST2(err, KErrNone); + TEST(fileSize > 0); + TEST2(TheDbFileSizes[i], fileSize); + + TPtr8 bufptr(TheBuf, 0, KMaxDbFileSize); + err = dbFile.Read(bufptr, fileSize); + TEST2(err, KErrNone); + TEST2(fileSize, bufptr.Length()); + + err = Mem::Compare(TheBuf, fileSize, TheDbFileData[i], TheDbFileSizes[i]); + TEST2(err, 0); + + dbFile.Close(); + } + delete dir; + } + +//////////////////////////////////////////////////////////////////////////////////////// + +//The backup client will return a series of data chunks representing +//one of more databases for the uid of the data owner. +//This data is stored in a file on the C drive for the purposes of the test +TInt TestBackupL(CSqlBurCallback &aBackupClient, RFs& aFs, TSecureId aUid, TDriveNumber aDrive, TInt aDataChunkSize = KBufferSize) + { + TFileName backupFileName; + backupFileName.Copy(KBackupFileTemplate); + backupFileName.Append((static_cast (aUid)).Name()); + + RFile file; + CleanupClosePushL(file); + TInt err = file.Replace(aFs, backupFileName, EFileWrite | EFileStream | EFileShareExclusive); + User::LeaveIfError(err); + aBackupClient.InitialiseGetProxyBackupDataL(aUid, aDrive); + + TBuf8 buf; + TPtr8 ptr((TUint8*)buf.Ptr(), aDataChunkSize); + TBool finishedFlag = EFalse; + TInt count = 0; + + do + { + aBackupClient.GetBackupDataSectionL(ptr, finishedFlag); + count += ptr.Length(); + err = file.Write(ptr); + User::LeaveIfError(err); + ptr.SetLength(0); + } + while(!finishedFlag); + + CleanupStack::PopAndDestroy(&file); + + if(count == 0) + { + User::Leave(KErrEof); + } + if(!FileExists(aFs, backupFileName)) + { + User::Leave(KErrNotFound); + } + TheTest.Printf(_L("Backup complete. %d bytes processed.\r\n"), count); + return count; + } + +//This sends the data in chunks form back to the BUR client +//for nupacking and restoration of the original databases files +TInt TestRestoreL(CSqlBurCallback &aRestoreClient, RFs& aFs, TSecureId aUid, TDriveNumber aDrive, TInt aDataChunkSize = KBufferSize) + { + TFileName backupFileName; + backupFileName.Copy(KBackupFileTemplate); + backupFileName.Append((static_cast (aUid)).Name()); + + RFile file; + CleanupClosePushL(file); + TInt err = file.Open(aFs, backupFileName, EFileRead | EFileShareExclusive); + User::LeaveIfError(err); + aRestoreClient.InitialiseRestoreProxyBaseDataL(aUid, aDrive); + + TBuf8 buf; + TPtr8 ptr((TUint8*)buf.Ptr(), aDataChunkSize); + TBool finishedFlag = EFalse; + + TInt fileSize = 0; + err = file.Size(fileSize); + User::LeaveIfError(err); + TInt count = fileSize; + + do + { + err = file.Read(ptr, aDataChunkSize); + User::LeaveIfError(err); + fileSize -= ptr.Length(); + finishedFlag = fileSize == 0; + aRestoreClient.RestoreBaseDataSectionL(ptr, finishedFlag); + ptr.SetLength(0); + } + while(fileSize > 0); + + CleanupStack::PopAndDestroy(&file); + + aRestoreClient.RestoreComplete(aDrive); + + if(!finishedFlag) + { + User::Leave(KErrEof); + } + + TheTest.Printf(_L("Restore complete. %d bytes processed.\r\n"), count); + return count; + } + +//Verifies the integrity of the backup file. +void TestArchiveIntegrityL(CSqlBurCallback &aBackupClient, RFs& aFs, TSecureId aUid) + { + RFile bkpFile; + CleanupClosePushL(bkpFile); + + TFileName backupFileName; + backupFileName.Copy(KBackupFileTemplate); + backupFileName.Append((static_cast (aUid)).Name()); + + TInt err = bkpFile.Open(aFs, backupFileName, EFileRead | EFileShareExclusive); + User::LeaveIfError(err); + + TBuf8 buf; + TPtr8 ptr((TUint8*)buf.Ptr(), buf.MaxLength()); + + TInt bkpFileSize = 0; + err = bkpFile.Size(bkpFileSize); + User::LeaveIfError(err); + + while(bkpFileSize > 0) + { + // get the checksum + err = bkpFile.Read(ptr, 16); // 8 UTF-16 characters + User::LeaveIfError(err); + if(ptr.Length() != 16) + { + User::Leave(KErrCorrupt); + } + TPtr ptr16((TUint16*) ptr.Ptr(), 8, 8); + TLex lex(ptr16); + TUint32 checksum; + lex.SkipSpace(); + err = lex.Val(checksum, EHex); + User::LeaveIfError(err); + bkpFileSize -= 16; + + // get the old file size + err = bkpFile.Read(ptr, 16); // 8 UTF-16 characters + User::LeaveIfError(err); + if(ptr.Length() != 16) + { + User::Leave(KErrCorrupt); + } + ptr16.Set((TUint16*) ptr.Ptr(), 8, 8); + lex.Assign(ptr16); + TUint32 oldFileSize; + lex.SkipSpace(); + err = lex.Val(oldFileSize, EHex); + User::LeaveIfError(err); + bkpFileSize -= 16; + + // get the backup file header version + err = bkpFile.Read(ptr, 8); // 4 UTF-16 characters + User::LeaveIfError(err); + ptr16.Set((TUint16*)ptr.Ptr(), 4, 4); + lex.Assign(ptr16); + TUint32 hdrVer; + lex.SkipSpace(); + err = lex.Val(hdrVer, EHex); + User::LeaveIfError(err); + bkpFileSize -= 8; + + // get the file size + err = bkpFile.Read(ptr, 32); // 16 UTF-16 characters + User::LeaveIfError(err); + if(ptr.Length() != 32) + { + User::Leave(KErrCorrupt); + } + ptr16.Set((TUint16*) ptr.Ptr(), 16, 16); + lex.Assign(ptr16); + TInt64 fileSize; + lex.SkipSpace(); + err = lex.Val(fileSize, EHex); + User::LeaveIfError(err); + bkpFileSize -= 32; + + // get the filename size + err = bkpFile.Read(ptr, 16); // 8 UTF-16 characters + User::LeaveIfError(err); + ptr16.Set((TUint16*)ptr.Ptr(), 8, 8); + lex.Assign(ptr16); + TUint32 fileNameSize; + lex.SkipSpace(); + err = lex.Val(fileNameSize, EHex); + User::LeaveIfError(err); + bkpFileSize -= 16; + + // get the filename + err = bkpFile.Read(ptr, fileNameSize * 2); // fileName UTF-16 characters + User::LeaveIfError(err); + if(ptr.Length() != (fileNameSize * 2)) + { + User::Leave(KErrCorrupt); + } + ptr16.Set((TUint16*) ptr.Ptr(), fileNameSize, fileNameSize); + lex.Assign(ptr16); + TParse tp; + tp.Set(ptr16, NULL, NULL); + TPtrC dbFileName = tp.Name(); + bkpFileSize -= fileNameSize * 2; + + // open a local file - replaces any previous one + RFile64 dbFile; + CleanupClosePushL(dbFile); + err = dbFile.Replace(aFs, dbFileName, EFileWrite | EFileShareExclusive); + User::LeaveIfError(err); + + // copy all the data (file size bytes) + TInt bytesLeftToRead = fileSize; + + while(bytesLeftToRead > 0) + { + TInt readSize = bytesLeftToRead > KBufferSize ? KBufferSize : bytesLeftToRead; + err = bkpFile.Read(ptr, readSize); + User::LeaveIfError(err); + if(ptr.Length() != readSize) + { + User::Leave(KErrCorrupt); + } + bytesLeftToRead -= readSize; + err = dbFile.Write(ptr, readSize); + User::LeaveIfError(err); + } + + bkpFileSize -= fileSize; + + // checksum the file + TUint64 checkSum64 = 0; + User::LeaveIfError(aBackupClient.CheckSum(dbFile, checkSum64)); + TUint32 checksum32 = checkSum64 & 0xFFFFFFFF; + + if(checksum != checksum32) + { + User::Leave(KErrCorrupt); + } + + // all done with this file + CleanupStack::PopAndDestroy(&dbFile); + err = aFs.Delete(dbFileName); + User::LeaveIfError(err); + } + + CleanupStack::PopAndDestroy(&bkpFile); + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4002 +@SYMTestCaseDesc Test for DEF113598 - "SQL, t_sqlbur unit test needs refactoring" + The test backups 2 test db files, then verifies the backup file integrity, + then restores the test db files content from the backup file. + At the end, the test checks that the restored test db files content is the + same as the content of the original test db file. +@SYMTestPriority High +@SYMTestActions Test for DEF113598 - "SQL, t_sqlbur unit test needs refactoring" +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF113598 +*/ +void FunctionalTest() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST(backupClient != NULL); + + //////////////////////////////////////// + + //Virtual functions - with default implementation + + (void)backupClient->GetExpectedDataSize(KTestDrive); + + (void)backupClient->GetDataChecksum(KTestDrive); + + TBool finished = EFalse; + TPtr8 ptr(0, 0, 0); + TRAP(err, backupClient->GetSnapshotDataL(KTestDrive, ptr, finished)); + TEST2(err, KErrNotSupported); + + TRAP(err, backupClient->InitialiseGetBackupDataL(KTestDrive)); + TEST2(err, KErrNotSupported); + + TRAP(err, backupClient->InitialiseRestoreBaseDataL(KTestDrive)); + TEST2(err, KErrNotSupported); + + TRAP(err, backupClient->InitialiseRestoreIncrementDataL(KTestDrive)); + TEST2(err, KErrNotSupported); + + TPtrC8 ptr2(KNullDesC8); + TRAP(err, backupClient->RestoreIncrementDataSectionL(ptr2, finished)); + TEST2(err, KErrNotSupported); + + TRAP(err, backupClient->AllSnapshotsSuppliedL()); + TEST2(err, KErrNone); + + TRAP(err, backupClient->ReceiveSnapshotDataL(KTestDrive, ptr2, finished)); + TEST2(err, KErrNotSupported); + + backupClient->TerminateMultiStageOperation(); + + //////////////////////////////////////// + + TInt bytesStored = 0; + TRAP(err, bytesStored = TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KClientUid, KTestDrive)); + TEST2(err, KErrNone); + + TheTest.Next(_L("Archive integrity test")); + + TRAP(err, TestArchiveIntegrityL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KClientUid)); + TEST2(err, KErrNone); + + delete backupClient; + + TheTest.Next(_L("Restore: functional test")); + + CSqlBurCallback* restoreClient = NULL; + TRAP(err, restoreClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST(restoreClient != NULL); + + TInt bytesRestored = 0; + TRAP(err, bytesRestored = TestRestoreL(*restoreClient, TheSqlSrvTestBurInterface->Fs(), KClientUid, KTestDrive)); + TEST2(err, KErrNone); + + TEST(bytesRestored == bytesStored); + + delete restoreClient; + + CompareDbContentWithBuf(TheSqlSrvTestBurInterface->Fs(), KTestDrive, KClientUid); + } + +TInt DoBackupL(TDriveNumber aDrive, TSecureId aUid) + { + CSqlBurCallback* backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface); + CleanupStack::PushL(backupClient); + TInt bytesStored = TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), aUid, aDrive); + CleanupStack::PopAndDestroy(backupClient); + return bytesStored; + } + +TInt DoRestoreL(TDriveNumber aDrive, TSecureId aUid) + { + CSqlBurCallback* restoreClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface); + CleanupStack::PushL(restoreClient); + TInt bytesRestored = TestRestoreL(*restoreClient, TheSqlSrvTestBurInterface->Fs(), aUid, aDrive); + CleanupStack::PopAndDestroy(restoreClient); + return bytesRestored; + } + +/** +@SYMTestCaseID SYSLIB-SQL-UT-4003 +@SYMTestCaseDesc Test for DEF113598 - "SQL, t_sqlbur unit test needs refactoring" + Under simulated OOM condition, the test backups 2 test db files, + then restores the test db files content from the backup file. + At the end, the test checks that the restored test db files content is the + same as the content of the original test db file. +@SYMTestPriority High +@SYMTestActions Test for DEF113598 - "SQL, t_sqlbur unit test needs refactoring" +@SYMTestExpectedResults Test must not fail +@SYMDEF DEF113598 +*/ +void OomTest() + { + /////////////////////////////////////////////////////////////////////////////// + TInt err = KErrNoMemory; + TInt bytesStored = 0; + TInt count = 0; + + for(count=1;err==KErrNoMemory;++count) + { + TInt startProcessHandleCount; + TInt startThreadHandleCount; + RThread().HandleCount(startProcessHandleCount, startThreadHandleCount); + + User::__DbgMarkStart(RHeap::EUser); + User::__DbgSetAllocFail(RHeap::EUser,RHeap::EFailNext, count); + TRAP(err, bytesStored = DoBackupL(KTestDrive, KClientUid)); + User::__DbgMarkEnd(RHeap::EUser, 0); + + TInt endProcessHandleCount; + TInt endThreadHandleCount; + RThread().HandleCount(endProcessHandleCount, endThreadHandleCount); + + TEST(startProcessHandleCount == endProcessHandleCount); + TEST(startThreadHandleCount == endThreadHandleCount); + } + TEST2(err, KErrNone); + TheTest.Printf(_L("OOM backup test succeeded at heap failure rate of %d\r\n"), count); + + /////////////////////////////////////////////////////////////////////////////// + TheTest.Next(_L("Restore: OOM test")); + err = KErrNoMemory; + TInt bytesRestored = 0; + + for(count=1;err==KErrNoMemory;++count) + { + TInt startProcessHandleCount; + TInt startThreadHandleCount; + RThread().HandleCount(startProcessHandleCount, startThreadHandleCount); + + User::__DbgMarkStart(RHeap::EUser); + User::__DbgSetAllocFail(RHeap::EUser,RHeap::EFailNext, count); + TRAP(err, bytesRestored = DoRestoreL(KTestDrive, KClientUid)); + User::__DbgMarkEnd(RHeap::EUser, 0); + + TInt endProcessHandleCount; + TInt endThreadHandleCount; + RThread().HandleCount(endProcessHandleCount, endThreadHandleCount); + + TEST(startProcessHandleCount == endProcessHandleCount); + TEST(startThreadHandleCount == endThreadHandleCount); + } + TEST2(err, KErrNone); + User::__DbgSetAllocFail(RHeap::EUser, RAllocator::ENone, 0); + TheTest.Printf(_L("OOM restore test succeeded at heap failure rate of %d\r\n"), count); + + TEST2(bytesStored, bytesRestored); + + CompareDbContentWithBuf(TheSqlSrvTestBurInterface->Fs(), KTestDrive, KClientUid); + } + +/** +@SYMTestCaseID PDS-SQL-UT-4143 +@SYMTestCaseDesc SQL Backup&Restore - data chunk size test. + The test uses an integer array of 10 elements with randomly generated data chunk sizes. + Then the test runs 10 backup iterations using each time different data chunk size. + After each backup iteration the test performs a restore operation and checks that the + data has been backup&restored without errors. +@SYMTestActions SQL Backup&Restore - data chunk size test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority Medium +@SYMREQ REQ12104 +*/ +void FunctionalTest2() + { + TTime now; + now.UniversalTime(); + TInt64 seed = now.Int64(); + + const TInt KArraySize = 10; + TInt dataChunks[10] = {2, 6, 0, 0, 0, 0, 0, 0, 0, 0}; + const TInt KMaxDataChunkSize = 50; + + for(TInt i=2;iFs(), KClientUid, KTestDrive, dataChunks[i])); + TEST2(err, KErrNone); + + TRAP(err, TestArchiveIntegrityL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KClientUid)); + TEST2(err, KErrNone); + + delete backupClient; + + CSqlBurCallback* restoreClient = NULL; + TRAP(err, restoreClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST(restoreClient != NULL); + + TInt bytesRestored = 0; + TRAP(err, bytesRestored = TestRestoreL(*restoreClient, TheSqlSrvTestBurInterface->Fs(), KClientUid, KTestDrive, dataChunks[i])); + TEST2(err, KErrNone); + + TEST(bytesRestored == bytesStored); + + delete restoreClient; + + CompareDbContentWithBuf(TheSqlSrvTestBurInterface->Fs(), KTestDrive, KClientUid); + } + } + +/** +@SYMTestCaseID PDS-SQL-UT-4144 +@SYMTestCaseDesc SQL Backup&Restore - legacy backup file format header test. + The 64-bit file system related changes made in the SQL server required some + changes to be made in the format of the backup file header. + The test checks that a backup file created with the previous format of the file header + can be restored without errors by the updated Backup&Restore implementation. +@SYMTestActions SQL Backup&Restore - legacy backup file format header test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority Medium +@SYMREQ REQ12104 +*/ +void LegacyFileFormatTest() + { + //KBackupFile2 is a database backup file with header version 0. + (void)TheSqlSrvTestBurInterface->Fs().Delete(KBackupFile2); + TInt rc = BaflUtils::CopyFile(TheSqlSrvTestBurInterface->Fs(), KBackupFile2Z, KBackupFile2); + TEST2(rc, KErrNone); + (void)TheSqlSrvTestBurInterface->Fs().SetAtt(KBackupFile2, 0, KEntryAttReadOnly); + + //Restore the databases from KBackupFile2. + CSqlBurCallback* restoreClient = NULL; + TRAP(rc, restoreClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST(restoreClient != NULL); + + RFile file; + rc = file.Open(TheSqlSrvTestBurInterface->Fs(), KBackupFile2, EFileRead | EFileShareExclusive); + TEST2(rc, KErrNone); + + TRAP(rc, restoreClient->InitialiseRestoreProxyBaseDataL(KClientUid, KTestDrive)); + TEST2(rc, KErrNone); + + TBuf8 buf; + TPtr8 ptr((TUint8*)buf.Ptr(), buf.MaxSize()); + TBool finishedFlag = EFalse; + + TInt fileSize = 0; + rc = file.Size(fileSize); + TEST2(rc, KErrNone); + + do + { + rc = file.Read(ptr); + TEST2(rc, KErrNone); + fileSize -= ptr.Size(); + finishedFlag = fileSize == 0; + TRAP(rc, restoreClient->RestoreBaseDataSectionL(ptr, finishedFlag)); + ptr.SetLength(0); + } + while(fileSize > 0); + + file.Close(); + + restoreClient->RestoreComplete(KTestDrive); + + TEST(finishedFlag); + + delete restoreClient; + + //At this point we have two restored databases: KTestDbFileName1 and KTestDbFileName2. + //The content of the restored file cannot be compared directly, because t_sqlattach uses the same test databases + //and modifies them. The original database content was stored without executing t_sqlattach. + //Hence a simple test is made: open the restored database, check if the database content can be accessed. + + RSqlDatabase db; + rc = db.Open(KTestDbFileName1); + TEST2(rc, KErrNone); + //The database contains this table: "TABLE C(A1 INTEGER, B2 BLOB)". + rc = db.Exec(_L("INSERT INTO C VALUES(100, 200)")); + TEST2(rc, 1); + RSqlStatement stmt; + rc = stmt.Prepare(db, _L("SELECT * FROM C")); + TEST2(rc, KErrNone); + while((rc = stmt.Next()) == KSqlAtRow) + { + } + stmt.Close(); + TEST2(rc, KSqlAtEnd); + db.Close(); + + rc = db.Open(KTestDbFileName2); + TEST2(rc, KErrNone); + //The database contains this table: "TABLE A1(F1 INTEGER , F2 INTEGER, B1 BLOB)" + rc = db.Exec(_L("INSERT INTO A1 VALUES(100, 200, NULL)")); + TEST2(rc, 1); + rc = stmt.Prepare(db, _L("SELECT * FROM A1")); + TEST2(rc, KErrNone); + while((rc = stmt.Next()) == KSqlAtRow) + { + } + stmt.Close(); + TEST2(rc, KSqlAtEnd); + db.Close(); + + (void)TheSqlSrvTestBurInterface->Fs().Delete(KBackupFile2); + } + +/** +@SYMTestCaseID PDS-SQL-UT-4192 +@SYMTestCaseDesc SQL Backup&Restore - empty backup file list test. + The test checks what will happen if the list with the files for backup is empty. + The GetBackupDataSectionL() should immediatelly set the flag parameter to true and do nothing. +@SYMTestActions SQL Backup&Restore - empty backup file list test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +@SYMDEF DEF145198 +*/ +void EmptyBackupFileListTest() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST(backupClient != NULL); + + TRAP(err, backupClient->InitialiseGetProxyBackupDataL(KNullUid, KTestDrive)); + TEST2(err, KErrNone); + + TBuf8<100> buf; + TPtr8 ptr((TUint8*)buf.Ptr(), 0, buf.MaxLength()); + TBool finishedFlag = EFalse; + TRAP(err, backupClient->GetBackupDataSectionL(ptr, finishedFlag)); + delete backupClient; + TEST2(err, KErrNone); + TEST(finishedFlag); + TEST2(buf.Length(), 0); + } + + +/** +@SYMTestCaseID PDS-SQL-UT-4193 +@SYMTestCaseDesc SQL Backup&Restore - file I/O error simulation test. + The test executes a backup, followed by a restore operation + in a file I/O error simulation loop. +@SYMTestActions SQL Backup&Restore - file I/O error simulation test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +@SYMDEF DEF145198 +*/ +void BackupRestoreFileIoErrTest() + { + //Make sure that the database content, just before the backup, will be copied to the test biffers. + //The buffers will be used during the restore testing for verification of the database content. + StoreDbContentToBuf(TheSqlSrvTestBurInterface->Fs(), KTestDrive, KClientUid); + + for(TInt fsError=KErrNotFound;fsError>=KErrBadName;--fsError) + { + TheTest.Printf(_L("===Backup&Restore, simulated file system error=%d\r\n"), fsError); + + TInt err = KErrGeneral; + TInt bytesStored = -1; + TInt it_cnt1 = 0; + for(;errFs().SetErrorCondition(fsError, it_cnt1); + TRAP(err, bytesStored = DoBackupL(KTestDrive, KClientUid)); + (void)TheSqlSrvTestBurInterface->Fs().SetErrorCondition(KErrNone); + __UHEAP_MARKEND; + } + TEST2(err, KErrNone); + + err = KErrGeneral; + TInt bytesRestored = -1; + TInt it_cnt2 = 0; + for(;errFs().SetErrorCondition(fsError, it_cnt2); + TRAP(err, bytesRestored = DoRestoreL(KTestDrive, KClientUid)); + (void)TheSqlSrvTestBurInterface->Fs().SetErrorCondition(KErrNone); + __UHEAP_MARKEND; + } + TEST2(err, KErrNone); + + TEST2(bytesStored, bytesRestored); + CompareDbContentWithBuf(TheSqlSrvTestBurInterface->Fs(), KTestDrive, KClientUid); + + TheTest.Printf(_L("Backup&Restore file I/O error simulation test succeeded at backup iteration %d and restore itreration %d\r\n"), it_cnt1 - 1, it_cnt2 - 1); + } + } + +/** +@SYMTestCaseID PDS-SQL-UT-4225 +@SYMTestCaseDesc SQL Backup - zero size file backup. + The test executes a backup on a file with zero size. +@SYMTestActions SQL Backup - zero size file backup. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +*/ +void BackupZeroSizeFileTest() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST2(err, KErrNone); + TEST(backupClient != NULL); + // + (void)TheSqlSrvTestBurInterface->Fs().Delete(KZeroSizeFile); + RFile file; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KZeroSizeFile, EFileRead | EFileWrite); + TEST2(err, KErrNone); + file.Close(); + // + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KZeroFileSizeUid, KTestDrive)); + TEST2(err, KErrNone); + //Write something to the file + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KZeroSizeFile, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData, "123456787989"); + err = file.Write(KData); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Do the restore. After the restore the file size should be 0. + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KZeroFileSizeUid, KTestDrive)); + TEST2(err, KErrNone); + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KZeroSizeFile, EFileRead | EFileWrite); + TEST2(err, KErrNone); + TInt size; + err = file.Size(size); + TEST2(err, KErrNone); + file.Close(); + TEST2(size, 0); + //Write something to the file + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KZeroSizeFile, EFileRead | EFileWrite); + TEST2(err, KErrNone); + err = file.Write(KData); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Call RestoreBaseDataSectionL() with 0 data in the input buffer and finished flag: false. + TRAP(err, backupClient->InitialiseRestoreProxyBaseDataL(KZeroFileSizeUid, KTestDrive)); + TEST2(err, KErrNone); + TPtrC8 zeroBuf; + TRAP(err, backupClient->RestoreBaseDataSectionL(zeroBuf, EFalse)); + TEST2(err, KErrNone); + //No restore in this case, + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KZeroSizeFile, EFileRead | EFileWrite); + TEST2(err, KErrNone); + err = file.Size(size); + TEST2(err, KErrNone); + file.Close(); + TEST(size > 0); + //Call RestoreBaseDataSectionL() with 0 data in the input buffer and finished flag: true. + TRAP(err, backupClient->InitialiseRestoreProxyBaseDataL(KZeroFileSizeUid, KTestDrive)); + TEST2(err, KErrNone); + TRAP(err, backupClient->RestoreBaseDataSectionL(zeroBuf, ETrue)); + TEST2(err, KErrNone); + //No restore in this case, + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KZeroSizeFile, EFileRead | EFileWrite); + TEST2(err, KErrNone); + err = file.Size(size); + TEST2(err, KErrNone); + file.Close(); + TEST(size > 0); + // + (void)TheSqlSrvTestBurInterface->Fs().Delete(KZeroSizeFile); + delete backupClient; + } + +/** +@SYMTestCaseID PDS-SQL-UT-4226 +@SYMTestCaseDesc SQL Restore - corrupted archive 1. + The test does a backup of a file with a non-zero size. + The the test modifies the archive, simulating a corruption. + The the test performs a restore from the archive. The corruption + should be detected and reported by SQL B&R code. +@SYMTestActions SQL Restore - corrupted archive 1. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +*/ +void CorruptedArchiveTest1() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST2(err, KErrNone); + TEST(backupClient != NULL); + //Create the test file that will be sent for backup + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + RFile file; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData1, "123456787989"); + err = file.Write(KData1); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Backup the file + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrNone); + //Modify the file, which was sent for backup + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData2, "ABCDEFGH"); + err = file.Write(KData2); + TEST2(err, KErrNone); + err = file.SetSize(KData2().Length()); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Corrupt the archive + TFileName backupFileName; + backupFileName.Copy(KBackupFileTemplate); + backupFileName.Append((static_cast (KTestClientUid1)).Name()); + err = file.Open(TheSqlSrvTestBurInterface->Fs(), backupFileName, EFileRead | EFileWrite); + TEST2(err, KErrNone); + TInt pos = -3; + err = file.Seek(ESeekEnd, pos); + TEST2(err, KErrNone); + _LIT8(KData3, "ERR"); + err = file.Write(KData3); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Try to restore the archive + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrCorrupt); + //Check that the file really has not been restored + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + TBuf8<50> data; + err = file.Read(data); + TEST2(err, KErrNone); + file.Close(); + TEST(data == KData2); + // + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + delete backupClient; + } + +/** +@SYMTestCaseID PDS-SQL-UT-4227 +@SYMTestCaseDesc SQL Restore - corrupted archive 2. + The test does a backup of a file with a non-zero size. + Then the test modifies the archive, byte after byte each step, + simulating a corruption. + The the test performs a restore from the archive. The corruption + should be detected and reported by SQL B&R code. +@SYMTestActions SQL Restore - corrupted archive 2. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +*/ +void CorruptedArchiveTest2() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST2(err, KErrNone); + TEST(backupClient != NULL); + //Create the test file that will be sent for backup + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + RFile file; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData1, "123456787989"); + err = file.Write(KData1); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Backup the file + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrNone); + //Modify the file, which was sent for backup + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData2, "ABCDEFGH"); + err = file.Write(KData2); + TEST2(err, KErrNone); + err = file.SetSize(KData2().Length()); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Make a copy of the modified file + CFileMan* fm = NULL; + TRAP(err, fm = CFileMan::NewL(TheSqlSrvTestBurInterface->Fs())); + TEST2(err, KErrNone); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1Bak); + err = fm->Copy(KTestFile1, KTestFile1Bak); + TEST2(err, KErrNone); + //Get the archive size + TFileName backupFileName; + backupFileName.Copy(KBackupFileTemplate); + backupFileName.Append((static_cast (KTestClientUid1)).Name()); + err = file.Open(TheSqlSrvTestBurInterface->Fs(), backupFileName, EFileRead | EFileWrite); + TEST2(err, KErrNone); + TInt size = 0; + err = file.Size(size); + TEST2(err, KErrNone); + file.Close(); + //Save a copy of the archive + (void)TheSqlSrvTestBurInterface->Fs().Delete(KBackupCopy); + err = fm->Copy(backupFileName, KBackupCopy); + TEST2(err, KErrNone); + //On each iteration step: corrupt the archive and try to do a restore from it. + for(TInt i=0;iFs(), backupFileName, EFileRead | EFileWrite); + TEST2(err, KErrNone); + TInt pos = i; + err = file.Seek(ESeekStart, pos); + TEST2(err, KErrNone); + TBuf8<1> byte; + err = file.Read(byte); + TEST2(err, KErrNone); + ++byte[0]; + err = file.Seek(ESeekStart, pos); + TEST2(err, KErrNone); + err = file.Write(byte); + TEST2(err, KErrNone); + if(i == (size - 1) && (size & 0x01) == 0) + {//Make the file size an odd number, just to test.... + err = file.Write(byte); + TEST2(err, KErrNone); + } + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Restore + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TheTest.Printf(_L("Iteration %d, err=%d\r\n"), i, err); + if(err == KErrNone) + { + //Delete the restored file. The reason that the restore didn't fail is because only the file data is + //protected with checksum. The restore file header - not. The restore completed, the data was restored + //to a file with different name. Or even to a file with the same name. Delete created file(s). + (void)fm->Delete(KTestDeleteMask1); + (void)fm->Delete(KTestDeleteMask2); + } + else + { + //The restore completed with an error. The file content is preserved. + //Check that the file content is the same. + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + TBuf8<50> data; + err = file.Read(data); + TEST2(err, KErrNone); + file.Close(); + TEST(data == KData2); + } + //Restore the file from the backup copy + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + err = fm->Copy(KTestFile1Bak, KTestFile1); + TEST2(err, KErrNone); + //Restore the archive from the good copy. + (void)TheSqlSrvTestBurInterface->Fs().Delete(backupFileName); + err = fm->Copy(KBackupCopy, backupFileName); + TEST2(err, KErrNone); + } + // + delete fm; + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1Bak); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KBackupCopy); + delete backupClient; + } + +/** +@SYMTestCaseID PDS-SQL-UT-4228 +@SYMTestCaseDesc SQL Backup&Restore on a drive different than KTestDrive (C: by default). + The test creates one database on KTestDrive and another database + with the same name on a drive different than KTestDrive. + Then the test backups the "not KTestDrive" drive and restores + the data after that. The test verifies that the backup&restore + really impacts only the other drive, not KTestDrive. +@SYMTestActions SQL Backup&Restore on a drive different than KTestDrive (C: by default). +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +*/ +void DbDriveTest() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST2(err, KErrNone); + TEST(backupClient != NULL); + // + TDriveUnit driveUnitDefault(KTestDrive); + TDriveName driveNameDefault = driveUnitDefault.Name(); + //Find a r/w drive, different than KTestDrive + TInt drive = EDriveA; + for(;drive<=EDriveZ;++drive) + { + if(drive == KTestDrive) + { + continue; + } + TDriveInfo driveInfo; + err = TheSqlSrvTestBurInterface->Fs().Drive(driveInfo, drive); + if(err != KErrNone) + { + continue; + } + if(driveInfo.iDriveAtt & KDriveAttRom) + { + continue; + } + // + TDriveUnit driveUnit(drive); + TDriveName driveName = driveUnit.Name(); + // + TVolumeInfo vinfo; + err = TheSqlSrvTestBurInterface->Fs().Volume(vinfo, drive); + if(err != KErrNone) + { + TheTest.Printf(_L("Drive %S, RFs::Volume() err=%d\r\n"), &driveName, err); + continue; + } + //R/W drive found. + TheTest.Printf(_L("Test drive: %S\r\n"), &driveName); + TParse parse; + err = parse.Set(KTestFile2, &driveName, 0); + TEST2(err, KErrNone); + //Create the test file that will be sent for backup + TPtrC fname1(parse.FullName()); + TheTest.Printf(_L("Test file 1: %S\r\n"), &fname1); + err = TheSqlSrvTestBurInterface->Fs().MkDirAll(parse.FullName()); + TEST(err == KErrNone || err == KErrAlreadyExists); + (void)TheSqlSrvTestBurInterface->Fs().Delete(parse.FullName()); + RFile file; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), parse.FullName(), EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData1, "123456787989"); + err = file.Write(KData1); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Create a test file with the same name on drive KTestDrive + err = parse.Set(KTestFile2, &driveNameDefault, 0); + TEST2(err, KErrNone); + TPtrC fname2(parse.FullName()); + TheTest.Printf(_L("Test file 2: %S\r\n"), &fname2); + (void)TheSqlSrvTestBurInterface->Fs().Delete(parse.FullName()); + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), parse.FullName(), EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData2, "ABCDEFG"); + err = file.Write(KData2); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Do the backup on "drive" + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid2, (TDriveNumber)drive)); + TEST2(err, KErrNone); + //Modify the file that was sent for backup + err = parse.Set(KTestFile2, &driveName, 0); + TEST2(err, KErrNone); + err = file.Open(TheSqlSrvTestBurInterface->Fs(), parse.FullName(), EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData3, "ABCDEFGHYYYYYY"); + err = file.Write(KData3); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Do the restore on "drive" + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid2, (TDriveNumber)drive)); + TEST2(err, KErrNone); + //Verify the content of the restored file + err = parse.Set(KTestFile2, &driveName, 0); + TEST2(err, KErrNone); + err = file.Open(TheSqlSrvTestBurInterface->Fs(), parse.FullName(), EFileRead | EFileWrite); + TEST2(err, KErrNone); + TBuf8<50> data; + err = file.Read(data); + TEST2(err, KErrNone); + file.Close(); + TEST(data == KData1); + //Verify the content of the file on drive KTestDrive. It should be the same as before the backup&restore. + err = parse.Set(KTestFile2, &driveNameDefault, 0); + TEST2(err, KErrNone); + err = file.Open(TheSqlSrvTestBurInterface->Fs(), parse.FullName(), EFileRead | EFileWrite); + TEST2(err, KErrNone); + err = file.Read(data); + TEST2(err, KErrNone); + file.Close(); + TEST(data == KData2); + //Cleanup + err = parse.Set(KTestFile2, &driveNameDefault, 0); + TEST2(err, KErrNone); + (void)TheSqlSrvTestBurInterface->Fs().Delete(parse.FullName()); + err = parse.Set(KTestFile2, &driveName, 0); + TEST2(err, KErrNone); + (void)TheSqlSrvTestBurInterface->Fs().Delete(parse.FullName()); + break; + } + delete backupClient; + if(drive > EDriveZ) + { + TheTest.Printf(_L("No R/W drive has been found, different than %S\r\n"), &driveNameDefault); + } + } + +/** +@SYMTestCaseID PDS-SQL-UT-4229 +@SYMTestCaseDesc SQL Backup&Restore with locked file. + The test creates two test files on the same drive and with the same uid. + Then the test backups the databases. After the backup the test simulates that + the first file is "in use". Then the test performs a restore. + The expected result: the locked file is not restored but the other file is restored. +@SYMTestActions SQL Backup&Restore with locked file. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +*/ +void LockFileTest() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST2(err, KErrNone); + TEST(backupClient != NULL); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile3); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile4); + //Create the files. File 1. + RFile file; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile3, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData1, "123456787989"); + err = file.Write(KData1); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //...file 2 + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile4, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData2, "ABCDEF"); + err = file.Write(KData2); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Backup + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid3, KTestDrive)); + TEST2(err, KErrNone); + //Modify the files. Keep the first file opened. + RFile file1; + err = file1.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile3, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData3, "YYYYYQQQQQQQQQQQ"); + err = file1.Write(KData3); + TEST2(err, KErrNone); + err = file1.Flush(); + TEST2(err, KErrNone); + //...file 2 + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile4, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData4, "5545495444j32322332234223432"); + err = file.Write(KData4); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Restore. The reported error should be KErrInUse. + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid3, KTestDrive)); + TEST2(err, KErrInUse); + //Close file 1 and check the content. It should be the same as after the backup + file1.Close(); + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile3, EFileRead | EFileWrite); + TEST2(err, KErrNone); + TBuf8<50> data; + err = file.Read(data); + TEST2(err, KErrNone); + file.Close(); + TEST(data == KData3); + //File2: check the content. It should be the same as before the backup + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile4, EFileRead | EFileWrite); + TEST2(err, KErrNone); + err = file.Read(data); + TEST2(err, KErrNone); + file.Close(); + TEST(data == KData2); + // + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile4); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile3); + delete backupClient; + } + +/** +@SYMTestCaseID PDS-SQL-UT-4230 +@SYMTestCaseDesc SQL Backup&Restore with locked file - test 2. + The test creates two test files on the same drive and with different uids. + Then the test backups the databases. After the backup the test simulates that + the first file is "in use". Then the test performs a restore. + The expected result: the locked file is not restored but the other file is restored. +@SYMTestActions SQL Backup&Restore with locked file - test 2. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +*/ +void LockFileTest2() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST2(err, KErrNone); + TEST(backupClient != NULL); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1);//KTestClientUid1 used + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile4);//KTestClientUid3 used + //Create the files. File 1. + RFile file; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData1, "123456787989"); + err = file.Write(KData1); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //...file 2 + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile4, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData2, "ABCDEF"); + err = file.Write(KData2); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Backup + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrNone); + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid3, KTestDrive)); + TEST2(err, KErrNone); + //Modify the files. Keep the first file opened. + RFile file1; + err = file1.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData3, "YYYYYQQQQQQQQQQQ"); + err = file1.Write(KData3); + TEST2(err, KErrNone); + err = file1.Flush(); + TEST2(err, KErrNone); + //...file 2 + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile4, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData4, "5545495444j32322332234223432"); + err = file.Write(KData4); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Restore the first file. The reported error should be KErrInUse. + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrInUse); + //Restore the second file. The reported error should be KErrNone. + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid3, KTestDrive)); + TEST2(err, KErrNone); + //Close file 1 and check the content. It should be the same as after the backup + file1.Close(); + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + TBuf8<50> data; + err = file.Read(data); + TEST2(err, KErrNone); + file.Close(); + TEST(data == KData3); + //File2: check the content. It should be the same as before the backup + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KTestFile4, EFileRead | EFileWrite); + TEST2(err, KErrNone); + err = file.Read(data); + TEST2(err, KErrNone); + file.Close(); + TEST(data == KData2); + // + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile4); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + delete backupClient; + } + +CDir* GetPrivateDirContent(TDriveNumber aDrive) + { + TDriveUnit driveUnit(aDrive); + TDriveName driveName = driveUnit.Name(); + TFileName path; + path.Copy(driveName); + path.Append(KPrivateDir); + _LIT(KMatchAllDbFiles, "*"); + path.Append(KMatchAllDbFiles); + //Do the search + CDir* fileNameCol = NULL; + TInt err = TheSqlSrvTestBurInterface->Fs().GetDir(path, KEntryAttNormal, ESortByName, fileNameCol); + TEST2(err, KErrNone); + return fileNameCol; + } + +/** +@SYMTestCaseID PDS-SQL-UT-4231 +@SYMTestCaseDesc SQL Backup&Restore - directory content test. + The test stores into an array information regarding all files in + SQL private datacage. Then the test backups one of the files and modifies + the file after that. Then the test does a restore. Expected result - the only + modifed file should be the file which was sent for backup. +@SYMTestActions SQL Backup&Restore - directory content test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +*/ +void DirectoryContentTest() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST2(err, KErrNone); + TEST(backupClient != NULL); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1);//KTestClientUid1 used + //Create the file + RFile file; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData1, "123456787989"); + err = file.Write(KData1); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Store file entries into an array + CDir* dirBeforeBackup = GetPrivateDirContent(KTestDrive); + //Backup + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrNone); + //Check dir content + CDir* dirAfterBackup = GetPrivateDirContent(KTestDrive); + TEST2(dirBeforeBackup->Count(), dirAfterBackup->Count()); + for(TInt i=0;iCount();++i) + { + const TEntry& entry1 = (*dirBeforeBackup)[i]; + const TEntry& entry2 = (*dirAfterBackup)[i]; + TheTest.Printf(_L("Entry1=%S, Entry2=%S\r\n"), &entry1.iName, &entry2.iName); + TBool rc = entry1.iAtt == entry2.iAtt; + TEST(rc); + rc = entry1.iSize == entry2.iSize; + TEST(rc); + rc = entry1.iModified == entry2.iModified; + TEST(rc); + rc = entry1.iType == entry2.iType; + TEST(rc); + rc = entry1.iName == entry2.iName; + TEST(rc); + } + delete dirAfterBackup; + //Modify the file + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + _LIT8(KData2, "ABCDEF"); + err = file.Write(KData2); + TEST2(err, KErrNone); + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Restore + User::After(2000000);//To force a change in the file time stamp (the restored file time stamp). + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrNone); + //Check dir content + CDir* dirAfterRestore = GetPrivateDirContent(KTestDrive); + TEST2(dirBeforeBackup->Count(), dirAfterRestore->Count()); + for(TInt i=0;iCount();++i) + { + const TEntry& entry1 = (*dirBeforeBackup)[i]; + const TEntry& entry2 = (*dirAfterRestore)[i]; + TheTest.Printf(_L("Entry1=%S, Entry2=%S\r\n"), &entry1.iName, &entry2.iName); + TBool rc = entry1.iAtt == entry2.iAtt; + TEST(rc); + rc = entry1.iSize == entry2.iSize; + TEST(rc); + if(entry1.iName.FindF(KTestFile1NameOnly) >= 0) + { + rc = entry1.iModified != entry2.iModified; + } + else + { + rc = entry1.iModified == entry2.iModified; + } + TEST(rc); + rc = entry1.iType == entry2.iType; + TEST(rc); + rc = entry1.iName == entry2.iName; + TEST(rc); + } + delete dirAfterRestore; + // + delete dirBeforeBackup; + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + delete backupClient; + } + +/** +@SYMTestCaseID PDS-SQL-UT-4232 +@SYMTestCaseDesc SQL Backup&Restore - large file test. + Backup and restore with a file with size bigger than 1 Mb. +@SYMTestActions SQL Backup&Restore - large file test. +@SYMTestExpectedResults Test must not fail +@SYMTestPriority High +*/ +void LargeFileTest() + { + CSqlBurCallback* backupClient = NULL; + TRAPD(err, backupClient = CSqlBurCallback::NewL(*TheSqlSrvTestBurInterface)); + TEST2(err, KErrNone); + TEST(backupClient != NULL); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1);//KTestClientUid1 used + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile2);//KTestClientUid2 used + //Allocate buffer for the data + const TInt KDataBufSize = 100000; + HBufC8* dataBuf = HBufC8::New(KDataBufSize); + TEST(dataBuf != NULL); + TPtr8 dataPtr = dataBuf->Des(); + //Create file 1 + const TInt KFileSize1 = 1201345; + RFile file; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile1, EFileRead | EFileWrite); + TEST2(err, KErrNone); + dataPtr.SetLength(dataPtr.MaxLength()); + const TChar KChar1(0x5A); + dataPtr.Fill(KChar1); + TInt len = KFileSize1; + while(len > 0) + { + TInt blockSize = Min(len, dataPtr.MaxLength()); + err = file.Write(dataPtr, blockSize); + TEST2(err, KErrNone); + len -= blockSize; + } + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Create file 2 + const TInt KFileSize2 = 1387651; + err = file.Replace(TheSqlSrvTestBurInterface->Fs(), KTestFile2, EFileRead | EFileWrite); + TEST2(err, KErrNone); + dataPtr.SetLength(dataPtr.MaxLength()); + const TChar KChar2(0xD5); + dataPtr.Fill(KChar2); + len = KFileSize2; + while(len > 0) + { + TInt blockSize = Min(len, dataPtr.MaxLength()); + err = file.Write(dataPtr, blockSize); + TEST2(err, KErrNone); + len -= blockSize; + } + err = file.Flush(); + TEST2(err, KErrNone); + file.Close(); + //Backup + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrNone); + TRAP(err, TestBackupL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid2, KTestDrive)); + TEST2(err, KErrNone); + //Delete the files + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile2); + //Restore + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid1, KTestDrive)); + TEST2(err, KErrNone); + TRAP(err, TestRestoreL(*backupClient, TheSqlSrvTestBurInterface->Fs(), KTestClientUid2, KTestDrive)); + TEST2(err, KErrNone); + //Check restored files content + const TPtrC KFileNames[] = {KTestFile1(), KTestFile2()}; + const TInt KFileSizes[] = {KFileSize1, KFileSize2}; + const TChar KSymbols[] = {KChar1, KChar2}; + for(TInt i=0;i<(sizeof(KFileNames)/sizeof(KFileNames[i]));++i) + { + err = file.Open(TheSqlSrvTestBurInterface->Fs(), KFileNames[i], EFileRead); + TEST2(err, KErrNone); + len = 0; + err = file.Size(len); + TEST2(err, KErrNone); + TEST2(len, KFileSizes[i]); + while(len > 0) + { + TInt blockSize = Min(len, dataPtr.MaxLength()); + err = file.Read(dataPtr, blockSize); + TEST2(err, KErrNone); + len -= blockSize; + for(TInt j=0;jFs().Delete(KTestFile2); + (void)TheSqlSrvTestBurInterface->Fs().Delete(KTestFile1); + delete backupClient; + } + +void DoMain() + { + TestEnvCreate(); + + TheTest.Start(_L("Store db content to memory buffer")); + StoreDbContentToBuf(TheSqlSrvTestBurInterface->Fs(), KTestDrive, KClientUid); + + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4002 Backup: functional test ")); + FunctionalTest(); + + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4003 Backup: OOM test ")); + OomTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4143 Backup&Restore: functional test 2")); + FunctionalTest2(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4144 Backup&Restore: legacy file format test")); + LegacyFileFormatTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4192 Backup&Restore: empty backup file list")); + EmptyBackupFileListTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4193 Backup: File I/O error simulation test")); + BackupRestoreFileIoErrTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4225 Zero size file - backup test")); + BackupZeroSizeFileTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4226 Restore test - corrupted archive 1")); + CorruptedArchiveTest1(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4227 Restore test - corrupted archive 2")); + CorruptedArchiveTest2(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4228 Backup&Restore test on a drive different than KTestDrive (C: by default)")); + DbDriveTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4229 Backup&Restore test with locked file")); + LockFileTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4230 Backup&Restore test with locked file 2")); + LockFileTest2(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4231 Backup&Restore - directory content test")); + DirectoryContentTest(); + + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4232 Backup&Restore - large file test")); + LargeFileTest(); + + TestEnvDestroy(); + } + +TInt E32Main() + { + TheTest.Title(); + + CTrapCleanup* tc = CTrapCleanup::New(); + TheTest(tc != NULL); + + __UHEAP_MARK; + + DoMain(); + + __UHEAP_MARKEND; + + TheTest.End(); + TheTest.Close(); + + delete tc; + + User::Heap().Check(); + return KErrNone; + }