diff -r 000000000000 -r 08ec8eefde2f persistentstorage/sql/TEST/t_sqlbur.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/sql/TEST/t_sqlbur.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,864 @@ +// Copyright (c) 2006-2009 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, "C:\\private\\10281e17\\"); + +const TUid KClientUid = {0x21212122}; // the data owner's UID + +_LIT(KBackupDir, "C:\\TEST\\"); +_LIT(KBackupFile, "C:\\TEST\\Backup.bak"); +_LIT(KBackupFile2Z, "Z:\\TEST\\t_sqlbur_backup_ver0.bak"); +_LIT(KBackupFile2, "C:\\TEST\\t_sqlbur_backup_ver0.bak"); + +const TUint KBufferSize = 2048; // used for reading backup files for validation + +static CActiveScheduler* TheScheduler = NULL; +static CSqlBurTestHarness* TheTestHarness = NULL; + +///////////////////////////////////// + +const TInt KMaxDbFileSize = 10 * 1024;//The max test db file size +const TInt KTestDbFileCnt = 2; + +//Test db files +_LIT(KTestFileName1,"[21212122]AADB2.db");//Created outside this test app +_LIT(KTestFileName2,"[21212122]BBDB2.db");//Created outside this test app +_LIT(KTestDbFileName1,"C:[21212122]AADB2.db"); +_LIT(KTestDbFileName2,"C:[21212122]BBDB2.db"); + +const TPtrC KTestFileNames[KTestDbFileCnt] = {KTestFileName1(), KTestFileName2()}; + +static TInt TheDbFileSizes[KTestDbFileCnt];//An array where the real db file size will be stored +static TUint8 TheDbFileData[KTestDbFileCnt][KMaxDbFileSize];//An array where the original db file content will be stored +static TUint8 TheBuf[KMaxDbFileSize]; + +///////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////// + +void TestEnvDestroy() + { + delete TheTestHarness; + TheTestHarness = 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__) + +/////////////////////////////////////////////////////////////////////////////////////// + +//CSqlBurTestHarness - test implementation of the MSqlSrvBurInterface, implemented in the production code by the SQL server. +CSqlBurTestHarness *CSqlBurTestHarness::New() + { + CSqlBurTestHarness* self = new CSqlBurTestHarness; + TEST(self != NULL); + self->Construct(); + return self; + } + +CSqlBurTestHarness::CSqlBurTestHarness() + { + } + +void CSqlBurTestHarness::Construct() + { + TInt err = iFs.Connect(); + TEST2(err, KErrNone); + err = iFs.MkDir(KBackupDir); + TEST(err == KErrNone || err == KErrAlreadyExists); + err = iFs.CreatePrivatePath(EDriveC); + TEST2(err, KErrNone); + } + +CSqlBurTestHarness::~CSqlBurTestHarness() + { + (void)iFs.Delete(KBackupFile); + 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 CSqlBurTestHarness::GetBackUpListL(TSecureId /*aUid*/, RArray& aFileList) + { + //TheTest.Printf(_L("Getting backup file list for SID=%x\r\n"),aUid); + for(TInt i=0;i& /*aFileList*/) + { + //TheTest.Printf(_L("Start \"backup\". %d files in the list.\r\n"), aFileList.Count()); + return ETrue; + } + +//Notification that a backup has ended +void CSqlBurTestHarness::EndBackup(const RArray& /*aFileList*/) + { + //TheTest.Printf(_L("End \"backup\". %d files in the list.\r\n"), aFileList.Count()); + } + +//Notification that a restore is starting +TBool CSqlBurTestHarness::StartRestoreL(TSecureId /*aUid*/) + { + //TheTest.Printf(_L("Start \"restore\" for UID=%X\r\n"), aUid); + return ETrue; + } + +//Notification that a restore has ended +void CSqlBurTestHarness::EndRestore(TSecureId /*aUid*/) + { + //TheTest.Printf(_L("End \"restore\" for UID=%X\r\n"), aUid); + } + +//Returns the file system resource handle to the caller. +RFs& CSqlBurTestHarness::Fs() + { + return iFs; + } + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +TBool FileExists(RFs& aFs, const TDesC& aFileName) + { + TEntry entry; + return aFs.Entry(aFileName, entry) == KErrNone; + } + +void TestEnvCreate() + { + TheScheduler = new CActiveScheduler; + TEST(TheScheduler != NULL); + + CActiveScheduler::Install(TheScheduler); + + TheTestHarness = CSqlBurTestHarness::New(); + TEST(TheTestHarness != NULL); + } + +//Reads the content of the db files and stores the content to a global memory buffer. +//That buffer content will be sued later for a verification of the restore process. +void StoreDbContentToBuf(RFs& aFs) + { + 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(); + } + } + +//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) + { + for(TInt i=0;i 0); + + RFile dbFile; + TInt err = dbFile.Open(aFs, KTestFileNames[i], EFileRead); + TEST2(err, KErrNone); + + TInt fileSize = 0; + err = dbFile.Size(fileSize); + TEST2(err, KErrNone); + TEST(fileSize > 0); + TEST(TheDbFileSizes[i] == fileSize); + + TPtr8 bufptr(TheBuf, 0, KMaxDbFileSize); + err = dbFile.Read(bufptr, fileSize); + TEST2(err, KErrNone); + TEST(fileSize == bufptr.Length()); + + err = Mem::Compare(TheBuf, fileSize, TheDbFileData[i], TheDbFileSizes[i]); + TEST2(err, 0); + + dbFile.Close(); + } + } + +//////////////////////////////////////////////////////////////////////////////////////// + +//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(CSqlBackupClient &aBackupClient, RFs& aFs, TInt aDataChunkSize = KBufferSize) + { + RFile file; + CleanupClosePushL(file); + TInt err = file.Replace(aFs, KBackupFile, EFileWrite | EFileStream | EFileShareExclusive); + User::LeaveIfError(err); + aBackupClient.InitialiseGetProxyBackupDataL(KClientUid, EDriveC); + + 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, KBackupFile)) + { + 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(CSqlBackupClient &aRestoreClient, RFs& aFs, TInt aDataChunkSize = KBufferSize) + { + RFile file; + CleanupClosePushL(file); + TInt err = file.Open(aFs, KBackupFile, EFileRead | EFileShareExclusive); + User::LeaveIfError(err); + aRestoreClient.InitialiseRestoreProxyBaseDataL(KClientUid, EDriveC); + + 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(EDriveC); + + if(!finishedFlag) + { + User::Leave(KErrEof); + } + for(TInt i=0;i 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 + TUint32 dbChecksum = aBackupClient.CheckSumL(dbFile) & 0xFFFFFFFF; + + if(checksum != dbChecksum) + { + 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() + { + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4002 Backup: functional test ")); + + CSqlBackupClient* backupClient = NULL; + TRAPD(err, backupClient = CSqlBackupClient::NewL(TheTestHarness)); + TEST(backupClient != NULL); + + //////////////////////////////////////// + + const TDriveNumber KDrive = EDriveC; + + //Virtual functions - with default implementation + + (void)backupClient->GetExpectedDataSize(KDrive); + + (void)backupClient->GetDataChecksum(KDrive); + + TBool finished = EFalse; + TPtr8 ptr(0, 0, 0); + TRAP(err, backupClient->GetSnapshotDataL(KDrive, ptr, finished)); + TEST2(err, KErrNotSupported); + + TRAP(err, backupClient->InitialiseGetBackupDataL(KDrive)); + TEST2(err, KErrNotSupported); + + TRAP(err, backupClient->InitialiseRestoreBaseDataL(KDrive)); + TEST2(err, KErrNotSupported); + + TRAP(err, backupClient->InitialiseRestoreIncrementDataL(KDrive)); + 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(KDrive, ptr2, finished)); + TEST2(err, KErrNotSupported); + + backupClient->TerminateMultiStageOperation(); + + //////////////////////////////////////// + + TInt bytesStored = 0; + TRAP(err, bytesStored = TestBackupL(*backupClient, TheTestHarness->Fs())); + TEST2(err, KErrNone); + + TheTest.Next(_L("Archive integrity test")); + + TRAP(err, TestArchiveIntegrityL(*backupClient, TheTestHarness->Fs())); + TEST2(err, KErrNone); + + delete backupClient; + + TheTest.Next(_L("Restore: functional test")); + + CSqlBackupClient* restoreClient = NULL; + TRAP(err, restoreClient = CSqlBackupClient::NewL(TheTestHarness)); + TEST(restoreClient != NULL); + + TInt bytesRestored = 0; + TRAP(err, bytesRestored = TestRestoreL(*restoreClient, TheTestHarness->Fs())); + TEST2(err, KErrNone); + + TEST(bytesRestored == bytesStored); + + delete restoreClient; + + CompareDbContentWithBuf(TheTestHarness->Fs()); + } + +TInt DoBackupL() + { + CSqlBackupClient* backupClient = CSqlBackupClient::NewLC(TheTestHarness); + TInt bytesStored = TestBackupL(*backupClient, TheTestHarness->Fs()); + CleanupStack::PopAndDestroy(backupClient); + return bytesStored; + } + +TInt DoRestoreL() + { + CSqlBackupClient* restoreClient = CSqlBackupClient::NewLC(TheTestHarness); + TInt bytesRestored = TestRestoreL(*restoreClient, TheTestHarness->Fs()); + 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() + { + /////////////////////////////////////////////////////////////////////////////// + TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SQL-UT-4003 Backup: OOM test ")); + 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()); + 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()); + 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); + + TEST(bytesStored == bytesRestored); + + CompareDbContentWithBuf(TheTestHarness->Fs()); + } + +/** +@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() + { + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4143 Backup&Restore: functional test 2")); + + 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(), dataChunks[i])); + TEST2(err, KErrNone); + + TRAP(err, TestArchiveIntegrityL(*backupClient, TheTestHarness->Fs())); + TEST2(err, KErrNone); + + delete backupClient; + + CSqlBackupClient* restoreClient = NULL; + TRAP(err, restoreClient = CSqlBackupClient::NewL(TheTestHarness)); + TEST(restoreClient != NULL); + + TInt bytesRestored = 0; + TRAP(err, bytesRestored = TestRestoreL(*restoreClient, TheTestHarness->Fs(), dataChunks[i])); + TEST2(err, KErrNone); + + TEST(bytesRestored == bytesStored); + + delete restoreClient; + + CompareDbContentWithBuf(TheTestHarness->Fs()); + } + } + +/** +@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() + { + TheTest.Next(_L(" @SYMTestCaseID:PDS-SQL-UT-4144 Backup&Restore: legacy file format test")); + + //KBackupFile2 is a database backup file with header version 0. + (void)TheTestHarness->Fs().Delete(KBackupFile2); + TInt rc = BaflUtils::CopyFile(TheTestHarness->Fs(), KBackupFile2Z, KBackupFile2); + TEST2(rc, KErrNone); + (void)TheTestHarness->Fs().SetAtt(KBackupFile2, 0, KEntryAttReadOnly); + + //Restore the databases from KBackupFile2. + CSqlBackupClient* restoreClient = NULL; + TRAP(rc, restoreClient = CSqlBackupClient::NewL(TheTestHarness)); + TEST(restoreClient != NULL); + + RFile file; + rc = file.Open(TheTestHarness->Fs(), KBackupFile2, EFileRead | EFileShareExclusive); + TEST2(rc, KErrNone); + + TRAP(rc, restoreClient->InitialiseRestoreProxyBaseDataL(KClientUid, EDriveC)); + 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(EDriveC); + + 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)TheTestHarness->Fs().Delete(KBackupFile2); + } + +void DoMain() + { + TestEnvCreate(); + + TheTest.Start(_L("Store db content to memory buffer")); + StoreDbContentToBuf(TheTestHarness->Fs()); + + FunctionalTest(); + + OomTest(); + + FunctionalTest2(); + + LegacyFileFormatTest(); + + TestEnvDestroy(); + } + +TInt E32Main() + { + TheTest.Title(); + + CTrapCleanup* tc = CTrapCleanup::New(); + TEST(tc != NULL); + + __UHEAP_MARK; + + DoMain(); + + __UHEAP_MARKEND; + + TheTest.End(); + TheTest.Close(); + + delete tc; + + User::Heap().Check(); + return KErrNone; + }