--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines_old/contactsmodel/tsrc/t_cnt_backup.cpp Tue Aug 31 15:05:21 2010 +0300
@@ -0,0 +1,2213 @@
+// Copyright (c) 2004-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 <e32test.h>
+#include <f32file.h>
+#include <s32file.h>
+#include <cntdb.h>
+#include <cntitem.h>
+#include <cntfield.h>
+#include <cntfldst.h>
+#include <coreappstest/testserver.h>
+
+#include <connect/sbeclient.h>
+
+#include "T_UTILS.H"
+#include "t_utils2.h"
+#include "t_cnt_backup.h"
+
+
+// cleanup version of test macro
+LOCAL_C void TestCondition(TBool aCondition, TInt aLineNumber);
+#define TEST_CONDITION(x) TestCondition(x, __LINE__)
+
+
+// test databases to create, for use by Contacts test clients
+_LIT(KBackupDatabaseFile1,"c:BackupTest1.cdb");
+_LIT(KBackupDatabaseFile2,"c:BackupTest2.cdb");
+_LIT(KBackupDatabaseFile3,"c:BackupTest3.cdb");
+
+
+// real location of Contacts db files
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+_LIT(KBackupDatabaseFileFullPath1,"c:\\private\\10003A73\\BackupTest1.cdb");
+_LIT(KBackupDatabaseFileFullPath2,"c:\\private\\10003A73\\BackupTest2.cdb");
+_LIT(KBackupDatabaseFileFullPath3,"c:\\private\\10003A73\\BackupTest3.cdb");
+_LIT(KBackupDestinationDatabasePath1,"c:\\t_cnt_backup\\BackupTest1.cdb");
+_LIT(KBackupDestinationDatabasePath2,"c:\\t_cnt_backup\\BackupTest2.cdb");
+_LIT(KBackupDestinationDatabasePath3,"c:\\t_cnt_backup\\BackupTest3.cdb");
+_LIT(KContactsBackupRegistrationDefaultDbFileFullPath, "c:\\private\\10003A73\\backup_registrationcontacts_cdb.xml");
+#else
+_LIT(KBackupDatabaseFileFullPath1,"c:\\private\\10003A73\\SQLite__BackupTest1.cdb");
+_LIT(KBackupDatabaseFileFullPath2,"c:\\private\\10003A73\\SQLite__BackupTest2.cdb");
+_LIT(KBackupDatabaseFileFullPath3,"c:\\private\\10003A73\\SQLite__BackupTest3.cdb");
+_LIT(KBackupDestinationDatabasePath1,"c:\\t_cnt_backup\\SQLite__BackupTest1.cdb");
+_LIT(KBackupDestinationDatabasePath2,"c:\\t_cnt_backup\\SQLite__BackupTest2.cdb");
+_LIT(KBackupDestinationDatabasePath3,"c:\\t_cnt_backup\\SQLite__BackupTest3.cdb");
+_LIT(KContactsBackupRegistrationDefaultDbFileFullPath, "c:\\private\\10003A73\\backup_registrationSQLite__contacts_cdb.xml");
+#endif
+
+
+// Contact model backup files
+_LIT(KContactsBackupRegistrationIniFileFullPath, "c:\\private\\10003A73\\backup_registration.xml");
+_LIT(KContactsIniBackupFileFullPath, "c:\\private\\10003A73\\Cntmodel.ini");
+_LIT(KBackupDestinationDirectory, "c:\\t_cnt_backup\\");
+_LIT(KBackupDestinationContactsIniPath,"c:\\t_cnt_backup\\Cntmodel.ini");
+_LIT(KRestoreDamagedDatabasePath,"z:\\t_cnt_backup_Corrupted_100065FF.cdb");
+
+// delays between Backup/Restoretest steps, to allow notifications to propagate to all components
+static const TInt KWaitForBackupNotification(15000000);
+static const TInt KWaitForClientToSettle(2000000);
+static const TInt KWaitForSystemToSettle(20000000);
+
+
+// Test databases have 10 contacts created, various contact Ids are used for different purposes
+static const TInt KNumContactsInDatabase= 10;
+static const TContactItemId KOpenContactId1 = 1;
+static const TContactItemId KOpenContactId2 = 2;
+static const TContactItemId KOpenContactId3 = 3;
+static const TContactItemId KSpeedDialContactId = 4;
+static const TContactItemId KReadContactId = 5;
+static const TInt KSpeedDialPositionOne = 1;
+
+
+_LIT(KAsyncFindMatch,"a");
+
+
+// global data for unit test
+_LIT(KTestName, "t_cnt_backup");
+static RTest test(KTestName);
+static RFs TheFsSession;
+
+
+/*
+ Class CBackupTestConductor drives the whole set of tests
+ 1. Check the Backup Registration file is present
+ 2. Check the Secure Backup Engine has processed it as we expect
+ 3. ... various Backup / Restore scenarios for contacts clients
+ */
+
+CBackupTestConductor* CBackupTestConductor::NewL()
+ {
+ CBackupTestConductor* self = new (ELeave) CBackupTestConductor();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CBackupTestConductor::~CBackupTestConductor()
+ {
+ // ensure test databases are deleted
+ CBackupTestConductor::DeleteDatabases();
+
+ // cleanup backup files
+ TheFsSession.Delete(KBackupDestinationContactsIniPath);
+ TheFsSession.Delete(KBackupDestinationDatabasePath1);
+ TheFsSession.Delete(KBackupDestinationDatabasePath2);
+ TheFsSession.Delete(KBackupDestinationDatabasePath3);
+ TheFsSession.RmDir(KBackupDestinationDirectory);
+ }
+
+
+CBackupTestConductor::CBackupTestConductor()
+ {
+ }
+
+
+void CBackupTestConductor::ConstructL()
+ {
+ const TInt err = TheFsSession.MkDirAll(KBackupDestinationDirectory);
+ if ((err != KErrNone) && (err != KErrAlreadyExists))
+ {
+ test.Printf(_L("Unable to create the directory %S\n"), &KBackupDestinationDirectory);
+ User::Leave(err);
+ }
+ }
+
+
+void CBackupTestConductor::RunTestsL()
+ {
+ // need databases for B&R testing
+ CreateDatabasesL();
+ // 1.x Check Backup Registration files
+ test.Start(_L("Backup registration files exist"));
+ TEST_CONDITION(CheckXMLBackupRegistrationExistsL());
+ test.End();
+
+
+ // framework that runs a Backup & Restore test cycle
+ CBackupTestFramework* backupFramework = CBackupTestFramework::NewLC();
+ CleanupStack::Check(backupFramework);
+
+ // 2. ... run all Backup / Restore test situations
+ backupFramework->DoBackupRestoreTestsL();
+
+ // delete framework
+ CleanupStack::PopAndDestroy(backupFramework);
+ }
+
+
+// demonstrates that database is populated correctly
+#ifdef _DEBUG
+void CBackupTestConductor::ShowFieldsL(CContactDatabase* aDb)
+#else
+void CBackupTestConductor::ShowFieldsL(CContactDatabase* /*aDb*/)
+#endif
+ {
+#if _DEBUG
+ CContactItem* contact = aDb->ReadContactLC(iFirstContactId);
+
+ CContactItemFieldSet& fields = contact->CardFields();
+ const TInt fieldCount = fields.Count();
+
+ for (TInt i = 0; i < fieldCount; i++)
+ {
+ CContactItemField &field = fields[i];
+ if (field.StorageType() == KStorageTypeText)
+ {
+ TPtrC fieldText = field.TextStorage()->Text();
+ TPtrC labelText = field.Label();
+ test.Printf(_L("--Field(%d) %S: %S \n\r"), i, &labelText, &fieldText);
+ }
+ }
+ CleanupStack::PopAndDestroy(contact);
+#endif
+ }
+
+
+/*
+ Populate the database - add TEN contacts, based on the default template,
+ setting FOUR fields. (Given name, Family name, phone number + Company name.)
+ Set the Company Name field to be the same as the name of the database.
+
+ @param aDb the CContactDatabase instance to add contacts to.
+ @param aFileName Database file name to put in the Company name field
+ */
+void CBackupTestConductor::PopulateDatabaseL(CContactDatabase* aDb,const TDesC& aFileName)
+ {
+ test.Printf(_L("Populating database %S\n"), &aFileName);
+ TInt index = 0;
+ TBool allDone = EFalse;
+
+ const TContactItemId templateId = aDb->TemplateId();
+ CContactItem* templateCard = aDb->ReadContactLC(templateId);
+
+ do
+ {
+ CContactCard* card = CContactCard::NewLC(templateCard);
+
+ CContactItemFieldSet& cardFields = card->CardFields();
+
+ TInt posLastName = cardFields.Find(KUidContactFieldGivenName);
+ TInt posFirstName = cardFields.Find(KUidContactFieldFamilyName);
+
+
+ switch (index)
+ { // (famous writers on computer topics)
+ case 0:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test1"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name1"));
+ break;
+
+ case 1:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test2"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name2"));
+ break;
+
+ case 2:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Thompson10"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name3"));
+ break;
+
+ case 3:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test3"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name4"));
+ break;
+
+ case 4:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test4"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name5"));
+ break;
+
+ case 5:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test5"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name6"));
+ break;
+
+ case 6:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test6"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name7"));
+ break;
+
+ case 7:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test7"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name8"));
+ break;
+
+ case 8:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test8"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name9"));
+ break;
+
+ case 9:
+ cardFields[posLastName].TextStorage()->SetTextL(_L("Test9"));
+ cardFields[posFirstName].TextStorage()->SetTextL(_L("Name10"));
+ // last contact
+ allDone = ETrue;
+ break;
+ }
+
+
+ // Set the telephone number
+ TInt posNumber = cardFields.Find(KUidContactFieldPhoneNumber);
+ if (posNumber != KErrNotFound)
+ {
+ cardFields[posNumber].SetMapping(KUidContactFieldVCardMapTEL);
+ cardFields[posNumber].TextStorage()->SetTextL(_L("1234"));
+ }
+
+
+ // set database file name as company name
+ TInt posCompanyName = cardFields.Find(KUidContactFieldCompanyName);
+ if (posCompanyName != KErrNotFound)
+ {
+ cardFields[posCompanyName].TextStorage()->SetTextL(aFileName);
+ }
+
+
+ iLastContactId = aDb->AddNewContactL(*card);
+ if (index == 0)
+ {
+ iFirstContactId = iLastContactId;
+ }
+
+ CleanupStack::PopAndDestroy(card);
+ ++index;
+
+ test.Printf(_L("."));
+ }
+ while (!allDone);
+
+ CleanupStack::PopAndDestroy(templateCard);
+
+ ShowFieldsL(aDb);
+ }
+
+// create THREE empty contacts databases then populate each
+void CBackupTestConductor::CreateDatabasesL()
+ {
+ // Create & close databases
+ CContactDatabase* db;
+ // Need to create the default data base if it does not exist to enusre
+ // prescence of backup registration file.
+ if (!CContactDatabase::DefaultContactDatabaseExistsL())
+ {
+ db = CContactDatabase::CreateL();
+ delete db;
+ }
+
+ test.Printf(_L("Creating database %S\n"), &KBackupDatabaseFile1);
+ db = CContactDatabase::ReplaceL(KBackupDatabaseFile1);
+ PopulateDatabaseL(db, KBackupDatabaseFile1);
+ delete db;
+
+ test.Printf(_L("Creating database %S\n"), &KBackupDatabaseFile2);
+ db = CContactDatabase::ReplaceL(KBackupDatabaseFile2);
+ PopulateDatabaseL(db, KBackupDatabaseFile2);
+ delete db;
+
+ test.Printf(_L("Creating database %S\n"), &KBackupDatabaseFile3);
+ db = CContactDatabase::ReplaceL(KBackupDatabaseFile3);
+ PopulateDatabaseL(db, KBackupDatabaseFile3);
+ delete db;
+ }
+
+
+void CBackupTestConductor::DeleteDatabases()
+ {
+ // Delete databases
+ TRAP_IGNORE(CContactDatabase::DeleteDatabaseL(KBackupDatabaseFile1));
+ TRAP_IGNORE(CContactDatabase::DeleteDatabaseL(KBackupDatabaseFile2));
+ TRAP_IGNORE(CContactDatabase::DeleteDatabaseL(KBackupDatabaseFile3));
+ }
+
+
+/*
+ Check that the Contact Model's Backup Registration files are present and > 0 bytes length
+ */
+TBool CBackupTestConductor::CheckXMLBackupRegistrationExistsL()
+ {
+ // Check the Contacts private area for the expected registration files
+ TEntry entry;
+
+ // See if initialisation registration file is in the directory on drive Z:
+ TInt error = TheFsSession.Entry(KContactsBackupRegistrationIniFileFullPath, entry);
+
+ if (error == KErrNotFound)
+ {
+ return EFalse;
+ }
+
+ User::LeaveIfError(error);
+
+ if(entry.iSize == 0)
+ {
+ // file is present but is empty
+ User::Leave(KErrCorrupt);
+ }
+
+ // See if default database registration file is in the directory on drive Z:
+ error = TheFsSession.Entry(KContactsBackupRegistrationDefaultDbFileFullPath, entry);
+
+ if (error == KErrNotFound)
+ {
+ return EFalse;
+ }
+
+ User::LeaveIfError(error);
+
+ if(entry.iSize == 0)
+ {
+ // file is present but is empty
+ User::Leave(KErrCorrupt);
+ }
+
+ // Found the registration files
+ return ETrue;
+ }
+
+
+//
+
+/*
+ Framework for simulating Contact Model clients
+
+ @param aDatabaseName database file name to open
+ @param aObserver Observer in Backup / Restore test framework to count Backup and Restore notifications
+ @param aContactViewObserver Observer in Backup / Restore test framework to count View Ready and Unavailable notifications
+ */
+CContactsClient* CContactsClient::NewLC(const TDesC& aDatabaseName, MBackupRestoreObserver* aObserver, MContactViewObserver& aContactViewObserver, TBool aCloseForBackup)
+ {
+ CContactsClient* self = new (ELeave) CContactsClient(aObserver, aContactViewObserver, aCloseForBackup);
+ CleanupStack::PushL(self);
+ self->ConstructL(aDatabaseName);
+ return self;
+ }
+
+
+CContactsClient::CContactsClient(MBackupRestoreObserver* aObserver, MContactViewObserver& aContactViewObserver, TBool aCloseForBackup)
+ : CActive(EPriorityStandard), iObserver(aObserver), iContactViewObserver(aContactViewObserver), iDatabaseIsOpen(EFalse), iCloseForBackup(aCloseForBackup), iOpenContacts(4)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CContactsClient::~CContactsClient()
+ {
+ Cancel();
+ CloseViews();
+ CloseDatabase();
+ iOpenContacts.ResetAndDestroy();
+
+ delete iDbName;
+ }
+
+
+void CContactsClient::StartActiveClose()
+ {
+ // start active object to close contact/view/database
+ // required as these can't be closed directly from the event handlers
+ if (!IsActive() && iDatabaseIsOpen)
+ {
+ TRequestStatus* pS = &iStatus;
+ User::RequestComplete(pS,0);
+ SetActive();
+ }
+ }
+
+void CContactsClient::DoCancel()
+ {
+ }
+
+
+void CContactsClient::RunL()
+ {
+ if (iStatus.Int() != KErrCancel)
+ {
+ CloseDatabase();
+ }
+ }
+
+void CContactsClient::CloseDatabase()
+ {
+ CloseContacts();
+ CloseViews();
+ iDatabaseIsOpen = EFalse;
+
+ if (iIdleFinder)
+ {
+ delete iIdleFinder;
+ iIdleFinder = NULL;
+ }
+
+ if (iItemFieldDef)
+ {
+ delete iItemFieldDef;
+ iItemFieldDef = NULL;
+ }
+
+ if (iActiveCompress)
+ {
+ delete iActiveCompress;
+ iActiveCompress = NULL;
+ }
+
+ if (iActiveRecover)
+ {
+ delete iActiveRecover;
+ iActiveRecover = NULL;
+ }
+
+ delete iNotifier;
+ iNotifier = NULL;
+ delete iDb;
+ iDb = NULL;
+ }
+
+
+void CContactsClient::ConstructL(const TDesC& aDatabaseName)
+ {
+ // remember the database name
+ iDbName = aDatabaseName.AllocL();
+ // open it
+ OpenDatabaseL();
+ }
+
+
+void CContactsClient::OpenDatabaseL()
+ {
+ // can only open once
+ if (iDatabaseIsOpen)
+ {
+ User::Leave(KErrInUse);
+ }
+
+ test.Printf(_L("Open database %S\n"), iDbName);
+ iDb = CContactDatabase::OpenL(iDbName->Des());
+ iDatabaseIsOpen = ETrue;
+ iNotifier = CContactChangeNotifier::NewL(*iDb,this);
+ }
+
+
+const TDesC& CContactsClient::DatabaseName()
+ {
+ return *iDbName;
+ }
+
+
+TBool CContactsClient::IsOpen()
+ {
+ return iDatabaseIsOpen;
+ }
+
+TBool CContactsClient::IsCloseForBackup()
+ {
+ return iCloseForBackup;
+ }
+
+void CContactsClient::OpenRemoteViewL()
+ {
+ if (iRemoteView != NULL)
+ {
+ User::Leave(KErrInUse);
+ }
+
+ RContactViewSortOrder viewSortOrder;
+
+ viewSortOrder.AppendL(KUidContactFieldFamilyName);
+ viewSortOrder.AppendL(KUidContactFieldGivenName);
+ viewSortOrder.AppendL(KUidContactFieldCompanyName);
+
+ iRemoteView = CContactRemoteView::NewL(iContactViewObserver, *iDb, viewSortOrder, EContactsOnly);
+
+ viewSortOrder.Close();
+ }
+
+
+void CContactsClient::OpenLocalViewL()
+ {
+ if (iLocalView != NULL)
+ {
+ User::Leave(KErrInUse);
+ }
+
+ RContactViewSortOrder viewSortOrder;
+
+ viewSortOrder.AppendL(KUidContactFieldFamilyName);
+ viewSortOrder.AppendL(KUidContactFieldGivenName);
+ viewSortOrder.AppendL(KUidContactFieldCompanyName);
+
+ iLocalView = CContactLocalView::NewL(iContactViewObserver, *iDb, viewSortOrder, EContactsOnly);
+
+ viewSortOrder.Close();
+ }
+
+
+void CContactsClient::CloseViews()
+ {
+ if (iLocalView)
+ {
+ iLocalView->Close(iContactViewObserver);
+ iLocalView = NULL;
+ }
+
+ if (iRemoteView)
+ {
+ iRemoteView->Close(iContactViewObserver);
+ iRemoteView = NULL;
+ }
+ }
+
+
+void CContactsClient::FindPhoneNumberL()
+ {
+ _LIT(KPhoneNumber, "1234");
+ const TInt KNumMatchDigit = 4;
+ CContactIdArray* array = iDb->MatchPhoneNumberL(KPhoneNumber, KNumMatchDigit);
+ CleanupStack::PushL(array);
+ TEST_CONDITION(array->Count() == 10);
+ CleanupStack::PopAndDestroy(array);
+ }
+
+
+// try to open a contact for edit
+void CContactsClient::OpenContactL(TContactItemId aContactId)
+ {
+ CContactItem* contact = iDb->OpenContactL(aContactId);
+ iOpenContacts.AppendL(contact);
+ }
+
+
+// try to commit an open contact
+void CContactsClient::CommitContactL(TContactItemId aContactId)
+ {
+ const TInt numOpenContacts = iOpenContacts.Count();
+
+ for (TInt j = 0; j < numOpenContacts; ++j)
+ {
+ CContactItem* tempContact = iOpenContacts[j];
+ if (tempContact->Id() == aContactId)
+ {
+ iDb->CommitContactL(*tempContact);
+ iOpenContacts.Remove(j);
+ delete tempContact;
+ return;
+ }
+ }
+ // contact isn't in open list
+ TEST_CONDITION(EFalse);
+ }
+
+
+// close any open contacts
+void CContactsClient::CloseContacts()
+ {
+ while (iOpenContacts.Count())
+ {
+ CContactItem* tempContact = iOpenContacts[0];
+ TRAP_IGNORE(iDb->CloseContactL(tempContact->Id()));
+ iOpenContacts.Remove(0);
+ delete tempContact;
+ }
+ }
+
+// try to Read the template Contact from database
+// and also, check that one record exists with the Company Name field set
+// to the clients database name
+void CContactsClient::ReadContactL()
+ {
+ CContactItem* contact = iDb->ReadContactLC(KReadContactId);
+ CleanupStack::PopAndDestroy(contact);
+
+ // find records with the Company Name field set
+ CContactItemFieldDef* fieldDef = new(ELeave) CContactItemFieldDef;
+ CleanupStack::PushL(fieldDef);
+ TFieldType fieldtype = KUidContactFieldCompanyName;
+ fieldDef->AppendL(fieldtype);
+ CContactIdArray* matchList = iDb->FindLC(iDbName->Des(),fieldDef);
+
+ // all added contacts should have this field initialised
+ TInt matchCount = matchList->Count();
+ TEST_CONDITION(matchCount == KNumContactsInDatabase);
+
+ CleanupStack::PopAndDestroy(2, fieldDef);
+ }
+
+
+void CContactsClient::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
+ {
+ /** Contacts DB about to be backed up */
+ if (aEvent.iType == EContactDbObserverEventBackupBeginning)
+ {
+ iRestore = EFalse;
+ iObserver->ContactsBackupRestoreObserver(*this, iRestore, ETrue);
+ }
+ /** Contacts DB about to be restored */
+ else if (aEvent.iType == EContactDbObserverEventRestoreBeginning)
+ {
+ iRestore = ETrue;
+ iObserver->ContactsBackupRestoreObserver(*this, iRestore, ETrue);
+ }
+ /** The backup/restore operation has completed. */
+ else if (aEvent.iType == EContactDbObserverEventBackupRestoreCompleted)
+ {
+ iObserver->ContactsBackupRestoreObserver(*this, iRestore, EFalse);
+ }
+ /** The restore operation has completed but the database could not be opened. */
+ else if (aEvent.iType == EContactDbObserverEventRestoreBadDatabase)
+ {
+ iObserver->ContactsBackupRestoreObserver(*this, iRestore, EFalse);
+ }
+ }
+
+
+void CContactsClient::StartAsyncFindL()
+ {
+ if (!iItemFieldDef)
+ {
+ iItemFieldDef = new(ELeave) CContactItemFieldDef();
+ iItemFieldDef->AppendL(KUidContactFieldGivenName);
+ iItemFieldDef->AppendL(KUidContactFieldFamilyName);
+ iItemFieldDef->AppendL(KUidContactFieldCompanyName);
+ iItemFieldDef->AppendL(KUidContactFieldPhoneNumber);
+ iItemFieldDef->AppendL(KUidContactFieldFax);
+ iItemFieldDef->AppendL(KUidContactFieldEMail);
+ iItemFieldDef->AppendL(KUidContactFieldUrl);
+ iItemFieldDef->AppendL(KUidContactFieldAddress);
+ iItemFieldDef->AppendL(KUidContactFieldLocality);
+ iItemFieldDef->AppendL(KUidContactFieldRegion);
+ iItemFieldDef->AppendL(KUidContactFieldPostcode);
+ iItemFieldDef->AppendL(KUidContactFieldCountry);
+ iItemFieldDef->AppendL(KUidContactFieldNote);
+ }
+
+ iIdleFinder = iDb->FindAsyncL(KAsyncFindMatch, iItemFieldDef, this);
+ }
+
+
+void CContactsClient::StartActiveCompactL()
+ {
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+ if (! iActiveCompress)
+ {
+ iActiveCompress = iDb->CreateCompressorLC();
+ CleanupStack::Pop();
+ }
+ iActiveCompress->SetObserver(this);
+#endif
+ }
+
+
+void CContactsClient::StartActiveRecoverL()
+ {
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+ if (! iActiveRecover)
+ {
+ iActiveRecover = iDb->CreateRecoverLC();
+ CleanupStack::Pop();
+ }
+ iActiveRecover->SetObserver(this);
+#endif
+ }
+
+
+void CContactsClient::StartIdleSorterL(TRequestStatus& aStatus)
+ {
+ CArrayFix<CContactDatabase::TSortPref>* sortOrder = new(ELeave) CArrayFixFlat<CContactDatabase::TSortPref>(3);
+ CleanupStack::PushL(sortOrder);
+
+ // prepare a sort order
+ sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldGivenName));
+ sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldFamilyName));
+ sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldCompanyName));
+
+ // starts Contacts Model Idle Sorter
+ iDb->SortAsyncL(sortOrder, aStatus);
+
+
+ // sortOrder ownership was passed to the Contact Model
+ CleanupStack::Pop(sortOrder);
+ }
+
+
+void CContactsClient::CompleteAsyncFindL()
+ {
+ // nothing to do Async Find completes in its own time
+ }
+
+
+void CContactsClient::CompleteActiveCompactL()
+ {
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+ TInt step;
+ while(iActiveCompress->Step())
+ {
+ step = iActiveCompress->StepsTogo();
+ TEST_CONDITION(step > 0);
+ }
+ step = iActiveCompress->StepsTogo();
+ TEST_CONDITION(step == 0);
+ delete iActiveCompress;
+ iActiveCompress = NULL;
+#endif
+ }
+
+
+void CContactsClient::CompleteActiveRecoverL()
+ {
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+ TInt step;
+ while(iActiveRecover->Step())
+ {
+ step = iActiveRecover->StepsTogo();
+ TEST_CONDITION(step > 0);
+ }
+ step = iActiveRecover->StepsTogo();
+ TEST_CONDITION(step == 0);
+ delete iActiveRecover;
+ iActiveRecover = NULL;
+#endif
+ }
+
+
+// class MContactUiCompactObserver
+void CContactsClient::Step(TInt /*aStep*/)
+ {
+ }
+
+
+void CContactsClient::HandleError(TInt /*aError*/)
+ {
+ }
+
+
+// class MIdleFindObserver
+void CContactsClient::IdleFindCallback()
+ {
+ }
+
+
+// Speed Dial Check, Remove and Set - for testing cntmodel.ini is Backed up and Restored correctly
+void CContactsClient::CheckSpeedDialSetL(TContactItemId aContactId, TInt aSpeedDialPosition)
+ {
+ HBufC* buf = HBufC::NewLC(100);
+ TPtr fieldContents = buf->Des();
+
+ TContactItemId id = iDb->GetSpeedDialFieldL(aSpeedDialPosition, fieldContents);
+ CleanupStack::PopAndDestroy(buf);
+
+ TEST_CONDITION(id == aContactId);
+ }
+
+
+void CContactsClient::RemoveSpeedDialL(TContactItemId aContactId, TInt aSpeedDialPosition)
+ {
+ iDb->RemoveSpeedDialFieldL(aContactId, aSpeedDialPosition);
+ }
+
+
+void CContactsClient::SetSpeedDialL(TContactItemId aContactId, TInt aSpeedDialPosition)
+ {
+ CContactItem* speedDialItem = iDb->OpenContactLX(aContactId);
+ CleanupStack::PushL(speedDialItem);
+ CContactItemFieldSet& cardFields = speedDialItem->CardFields();
+
+ TInt posNumber = cardFields.Find(KUidContactFieldPhoneNumber);
+
+ iDb->SetFieldAsSpeedDialL(*speedDialItem, posNumber, aSpeedDialPosition);
+ CleanupStack::PopAndDestroy(speedDialItem);
+ CleanupStack::Pop(); // Lock Record
+ }
+
+
+//
+// Backup and Restore Test Framework class
+//
+
+CBackupHelper* CBackupHelper::NewL(RPIMTestServer& aTestServer)
+ {
+ CBackupHelper* self = new(ELeave) CBackupHelper(aTestServer);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+CBackupHelper::CBackupHelper(RPIMTestServer& aTestServer) :
+ iTestServ (aTestServer)
+ {
+ }
+
+
+void CBackupHelper::ConstructL()
+ {
+ /* Initialise the drive list to empty and then get drive list data from
+ File Server.
+ Required before Backup and Restore testing
+ */
+ iDriveList.FillZ();
+ User::LeaveIfError(TheFsSession.DriveList(iDriveList));
+
+ iBackupClient = conn::CSBEClient::NewL();
+ }
+
+
+CBackupHelper::~CBackupHelper()
+ {
+ delete iBackupClient;
+ }
+
+
+void CBackupHelper::StartBackupL(conn::TBURPartType aBURPartType, conn::TBackupIncType aBackupIncType)
+ {
+ /* Use the Secure Backup Engine API to "start" a backup. Ultimate effect
+ is to cause CContactsClient::HandleDatabaseEventL() to be called.
+ This happens indirectly through CLockSrvServer::BackupBeginningL()/
+ BackupCompletedL()/RestoreBeginningL()/RestoreCompletedL() methods.
+ These methods are implementations for MBackupRestoreNotificatioObserver
+ which monitors changes in the P&S property conn::KUidBackupRestoreKey.
+ This P&S property is changed by calling the Secure Backup Engine API
+ below.
+ */
+ iBackupClient->SetBURModeL(iDriveList, aBURPartType, aBackupIncType);
+ }
+
+
+void CBackupHelper::EndBackupL()
+ {
+ /* Use the Secure Backup Engine API to "end" a backup. Ultimate effect
+ is to cause CContactsClient::HandleDatabaseEventL() to be called.
+ This happens indirectly through CLockSrvServer::BackupBeginningL()/
+ BackupCompletedL()/RestoreBeginningL()/RestoreCompletedL() methods.
+ These methods are implementations for MBackupRestoreNotificatioObserver
+ which monitors changes in the P&S property conn::KUidBackupRestoreKey.
+ This P&S property is changed by calling the Secure Backup Engine API
+ below.
+ */
+ iBackupClient->SetBURModeL(iDriveList, conn::EBURNormal, conn::ENoBackup);
+ }
+
+
+void CBackupHelper::StartRestoreL()
+ {
+ /* Use the Secure Backup Engine API to "start" a restore. Ultimate effect
+ is to cause CContactsClient::HandleDatabaseEventL() to be called.
+ This happens indirectly through CLockSrvServer::BackupBeginningL()/
+ BackupCompletedL()/RestoreBeginningL()/RestoreCompletedL() methods.
+ These methods are implementations for MBackupRestoreNotificatioObserver
+ which monitors changes in the P&S property conn::KUidBackupRestoreKey.
+ This P&S property is changed by calling the Secure Backup Engine API
+ below.
+ */
+ iBackupClient->SetBURModeL(iDriveList, conn::EBURRestoreFull, conn::EBackupBase);
+ }
+
+
+void CBackupHelper::EndRestoreL()
+ {
+ /* Use the Secure Backup Engine API to "end" a restore. Ultimate effect
+ is to cause CContactsClient::HandleDatabaseEventL() to be called.
+ This happens indirectly through CLockSrvServer::BackupBeginningL()/
+ BackupCompletedL()/RestoreBeginningL()/RestoreCompletedL() methods.
+ These methods are implementations for MBackupRestoreNotificatioObserver
+ which monitors changes in the P&S property conn::KUidBackupRestoreKey.
+ This P&S property is changed by calling the Secure Backup Engine API
+ below.
+ */
+ iBackupClient->SetBURModeL(iDriveList, conn::EBURNormal, conn::ENoBackup);
+ }
+
+
+
+
+//
+// Simulate Backup of .ini file. Indicating if the operation was a success.
+//
+TBool CBackupHelper::SimulateIniBackup()
+ {
+ // Backup CntModel.ini file.
+ TRAPD(error, iTestServ.CopyFileL(KContactsIniBackupFileFullPath,
+ KBackupDestinationContactsIniPath))
+
+ if (error != KErrNone)
+ {
+ test.Printf(_L("Copy failed with error %i"), error);
+ return EFalse;
+ }
+ return ETrue;
+ }
+
+
+//
+// Simulate Backup of database(s). Indicating if the operation was a success.
+//
+TBool CBackupHelper::SimulateDbBackup()
+ {
+ // backup databases
+ TRAPD(error, iTestServ.CopyFileL(KBackupDatabaseFileFullPath1, KBackupDestinationDatabasePath1))
+
+ if (error == KErrNone)
+ {
+ TRAP(error, iTestServ.CopyFileL(KBackupDatabaseFileFullPath2, KBackupDestinationDatabasePath2))
+ }
+
+ if (error == KErrNone)
+ {
+ TRAP(error, iTestServ.CopyFileL(KBackupDatabaseFileFullPath3, KBackupDestinationDatabasePath3))
+ }
+
+ if (error != KErrNone)
+ {
+ test.Printf(_L("Copy failed with error %i"), error);
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+
+//
+// Simulate restore of .ini file. Indicating if the operation was a success.
+//
+TBool CBackupHelper::SimulateIniRestore()
+ {
+ // Restore CntModel.ini file.
+ TRAPD(error, iTestServ.CopyFileL(KBackupDestinationContactsIniPath, KContactsIniBackupFileFullPath))
+
+ if (error != KErrNone)
+ {
+ test.Printf(_L("Copy failed with error %i"), error);
+ return EFalse;
+ }
+ return ETrue;
+ }
+
+
+//
+// Simulate restore of database(s). Indicating if the operation was a success.
+//
+TBool CBackupHelper::SimulateDbRestore()
+ {
+ // restore databases
+ TRAPD(error, iTestServ.CopyFileL(KBackupDestinationDatabasePath1, KBackupDatabaseFileFullPath1))
+
+ if (error == KErrNone)
+ {
+ TRAP(error, iTestServ.CopyFileL(KBackupDestinationDatabasePath2, KBackupDatabaseFileFullPath2))
+ }
+
+ if (error == KErrNone)
+ {
+ TRAP(error, iTestServ.CopyFileL(KBackupDestinationDatabasePath3, KBackupDatabaseFileFullPath3))
+ }
+
+ if (error != KErrNone)
+ {
+ test.Printf(_L("Copy failed with error %i"), error);
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+//
+// Simulate restoring a corrupted database.
+//
+TBool CBackupHelper::SimulateDamagedDbRestore()
+ {
+ // Restore first one from a damaged and the rest from a good copy.
+ TRAPD(error, iTestServ.CopyFileL(KRestoreDamagedDatabasePath, KBackupDatabaseFileFullPath1))
+
+ if (error == KErrNone)
+ {
+ TRAP(error, iTestServ.CopyFileL(KBackupDestinationDatabasePath2, KBackupDatabaseFileFullPath2))
+ }
+
+ if (error == KErrNone)
+ {
+ TRAP(error, iTestServ.CopyFileL(KBackupDestinationDatabasePath3, KBackupDatabaseFileFullPath3))
+ }
+
+ if (error != KErrNone)
+ {
+ test.Printf(_L("Copy failed with error %i"), error);
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+//
+// Backup and Restore Test Framework class
+//
+static const CBackupTestFramework::TBackupRestoreTestCase BackupTestCases[] =
+ {
+ /* iTestTitle, iNumDatabases, iClientsPerDatabase, iActivity, iCloseForBackup, iExpectedBackupSuccess */
+
+ /*
+ Test client activities that DO NOT BLOCK Backup / Restore
+ Backup and Restore should always succeed, tests are in pairs:
+ 1. does not respond to Backup
+ 2. closes all resources when Backup or Restore begin
+ */
+
+ // Single client per database - Backup and Restore should always succeed
+ {
+ (TText*) L"Clients that keep CContactDatabase Open",
+ 3, 1, CBackupTestFramework::EIdleClient, ETrue, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Clients that close CContactDatabase",
+ 3, 1, CBackupTestFramework::EIdleClient, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+ {
+ (TText*) L"Clients that keep CContactDatabase Open; Restore fails",
+ 3, 1, CBackupTestFramework::ERestoreCorruptDbTest, ETrue, CBackupTestFramework::EAllOpenForBackup , conn::EBackupBase
+ },
+
+ // clients open a contact Local View - Backup and Restore should always succeed
+ {
+ (TText*) L"Clients that keep a Local View Open",
+ 1, 1, CBackupTestFramework::EOpenLocalView, ETrue, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Clients that close Local View and database",
+ 1, 1, CBackupTestFramework::EOpenLocalView, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+ // clients open a contact Remote View - Backup and Restore should always succeed
+ {
+ (TText*) L"Clients that keep a Remote View Open",
+ 1, 1, CBackupTestFramework::EOpenRemoteView, ETrue, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Clients that close Remote View and database",
+ 1, 1, CBackupTestFramework::EOpenRemoteView, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+ // Multiple clients per database - Backup and Restore should always succeed
+ {
+ (TText*) L"Multiple clients per database, all keep CContactDatabase Open",
+ 3, 3, CBackupTestFramework::EIdleClient, ETrue, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Multiple clients per database, all close CContactDatabase",
+ 3, 3, CBackupTestFramework::EIdleClient, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+
+ {
+ (TText*) L"Two clients per database, one close and one keep CContactDatabase open",
+ 2, 2, CBackupTestFramework::EIdleClient, ETrue, CBackupTestFramework::EHalfCloseForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Two clients per database, one closes its contact item and one keeps its contact item open",
+ 1, 2, CBackupTestFramework::EMultipleOpenOneContactForEdit, EFalse, CBackupTestFramework::EHalfCloseForBackup, conn::EBackupBase
+ },
+
+ /*
+ Test client activities that should BLOCK Backup / Restore
+ Tests are in pairs:
+ 1. does not respond to Backup or Restore - (tests that Backup & Restore fail)
+ 2. closes all resources when Backup or Restore begin - (tests that Backup & Restore succeed)
+ */
+
+ // Client opens contact for edit - Backup and Restore succeed when resources are freed
+ {
+ (TText*) L"Client opens contact for edit, resources kept open",
+ 1, 1, CBackupTestFramework::EOpenOneContactForEdit, EFalse, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Client opens contact for edit, resources released",
+ 1, 1, CBackupTestFramework::EOpenOneContactForEdit, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+ // Open two contacts for edit - Backup and Restore succeed when resources are freed
+ {
+ (TText*) L"Open two contacts for edit, resources kept open",
+ 1, 1, CBackupTestFramework::EOpenTwoContactsForEdit, EFalse, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Open two contacts for edit, resources released",
+ 1, 1, CBackupTestFramework::EOpenTwoContactsForEdit, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+ // Active Compact - Backup and Restore succeed when resources are free
+ {
+ (TText*) L"Active Compact, resources kept open",
+ 1, 1, CBackupTestFramework::EContactsActiveCompact, EFalse, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Active Compact, resources released",
+ 1, 1, CBackupTestFramework::EContactsActiveCompact, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+ // Active Recover - Backup and Restore succeed when resources are free
+ {
+ (TText*) L"Active Recover, resources kept open",
+ 1, 1, CBackupTestFramework::EContactsActiveRecover, EFalse, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Active Recover, resources released",
+ 1, 1, CBackupTestFramework::EContactsActiveRecover, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+#endif
+
+ // Async Find - Backup and Restore succeed when resources are freed
+ {
+ (TText*) L"Async Find - Blocks Backup / Restore until it completes",
+ 1, 1, CBackupTestFramework::EContactsAsyncFind, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+ // Contacts Idle Sorter - Backup and Restore succeed when it completes and resources are freed
+ {
+ (TText*) L"Contacts Idle Sorter - Blocks Backup / Restore until it completes",
+ 1, 1, CBackupTestFramework::EContactsIdleSorter, ETrue, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+
+ // Contacts client updates SpeedDial and checks this is Backed-up and Restored
+ {
+ (TText*) L"Contacts test for .Ini file Backup and Restore (clients don't close)",
+ 1, 1, CBackupTestFramework::EContactsIniFileTest, ETrue, CBackupTestFramework::EAllOpenForBackup, conn::EBackupBase
+ },
+ // Open Remote View and open a contact - Backup and Restore succeed when it completes and resources are freed
+ {
+ (TText*) L"Multiple clients that create a remote view and open a contact(clients close)",
+ 1, 2, CBackupTestFramework::EOpenRemoteViewOneContactForEdit, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+ {
+ (TText*) L"Contacts test for .Ini file Backup and Restore(clients close",
+ 1, 1, CBackupTestFramework::EContactsIniFileTest, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupBase
+ },
+
+ //
+ // Incremental Backup and Restore. Should always succeed.
+ {
+ (TText*) L"INCREMENTAL: Clients that keep CContactDatabase Open",
+ 3, 1, CBackupTestFramework::EIdleClient, ETrue, CBackupTestFramework::EAllOpenForBackup, conn::EBackupIncrement
+ },
+ {
+ (TText*) L"INCREMENTAL: Client opens contact for edit, resources released",
+ 1, 1, CBackupTestFramework::EOpenOneContactForEdit, ETrue, CBackupTestFramework::EAllCloseForBackup, conn::EBackupIncrement
+ }
+ };
+
+
+CBackupTestFramework* CBackupTestFramework::NewLC()
+ {
+ CBackupTestFramework* self = new(ELeave) CBackupTestFramework();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+
+CBackupTestFramework::CBackupTestFramework() : CTimer(CActive::EPriorityStandard)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+
+void CBackupTestFramework::ConstructL()
+ {
+ CTimer::ConstructL();
+
+ // Test server used for copying files around.
+ User::LeaveIfError(iTestServ.Connect());
+ iBackupHelper = CBackupHelper::NewL(iTestServ);
+ }
+
+
+CBackupTestFramework::~CBackupTestFramework()
+ {
+ // cleanup from current test case
+ CTimer::Cancel();
+
+ iTestServ.Close();
+
+ delete iBackupHelper;
+ iContactClientSession.ResetAndDestroy();
+ }
+
+
+void CBackupTestFramework::DoBackupRestoreTestsL()
+ {
+ const TInt testCount = sizeof(BackupTestCases) / sizeof(CBackupTestFramework::TBackupRestoreTestCase);
+
+ test.Printf(_L("Iterate through all %i Backup and Restore test cases"), testCount);
+
+ for (TInt testIndex = 0; testIndex < testCount; ++testIndex)
+ {
+ iTestCase = &BackupTestCases[testIndex];
+ BackupRestoreTestL();
+ }
+ }
+
+
+
+// Method to setup the Use Case under test
+// returns ETrue if TrequestStatus was used
+TBool CBackupTestFramework::PrepareBackupClientTestCaseL(TRequestStatus& aStatus)
+ {
+ TBool asyncRequest = EFalse;
+
+ // for every database we are required to open
+ for (TInt dbCount = 1; (dbCount <= iTestCase->iNumDatabases) && (!asyncRequest); ++dbCount)
+ {
+ switch (dbCount)
+ {
+ case 1:
+ asyncRequest = PrepareTestCaseL(KBackupDatabaseFile1(), aStatus);
+ break;
+
+ case 2:
+ asyncRequest = PrepareTestCaseL(KBackupDatabaseFile2(), aStatus);
+ break;
+
+ case 3:
+ asyncRequest = PrepareTestCaseL(KBackupDatabaseFile3(), aStatus);
+ break;
+
+ default: // something is wrong with test code
+ User::Invariant();
+ }
+ }
+
+ return asyncRequest;
+ }
+
+
+// Method to implement the Use Case under test
+TBool CBackupTestFramework::PrepareTestCaseL(const TDesC& aDatabaseName, TRequestStatus& aStatus)
+ {
+ TBool asyncRequest = EFalse;
+
+ // at least one, possibly more, clients per database
+ for (TInt clClient = 1; clClient <= iTestCase->iClientsPerDatabase; ++clClient)
+ {
+ // open database
+ TBool isCloseForBackup = ETrue;
+
+ switch(iTestCase->iCloseForBackup)
+ {
+ case EAllOpenForBackup:
+ isCloseForBackup = EFalse;
+ break;
+ case EHalfCloseForBackup:
+ if(clClient > iTestCase->iClientsPerDatabase/2)
+ {
+ isCloseForBackup = EFalse;
+ }
+ break;
+ case EAllCloseForBackup:
+ default:
+ break;
+ }
+
+ CContactsClient* db = NewDatabaseClientL(aDatabaseName, isCloseForBackup);
+
+
+ // specific test case behaviour
+ switch (iTestCase->iActivity)
+ {
+ // activities that do not block backup / restore
+ case EIdleClient:
+ case ERestoreCorruptDbTest:
+ // demonstrate database is open, read from it
+ test.Next(_L("Read a contact from database"));
+ db->ReadContactL();
+ break;
+
+ case EOpenLocalView:
+ test.Next(_L("open contact Local View"));
+ db->OpenLocalViewL();
+ break;
+
+ case EOpenRemoteView:
+ test.Next(_L("open contact Remote View"));
+ db->OpenRemoteViewL();
+ break;
+
+ // activities that can block backup / restore
+ case EOpenOneContactForEdit:
+ test.Next(_L("Open a contact from database"));
+ db->OpenContactL(KOpenContactId1);
+ break;
+
+ case EOpenTwoContactsForEdit:
+ test.Next(_L("Open 2 contacts from database"));
+ db->OpenContactL(KOpenContactId1);
+ db->OpenContactL(KOpenContactId2);
+ break;
+
+ case EContactsAsyncFind:
+ test.Next(_L("Start Async Find on database"));
+ db->StartAsyncFindL();
+ break;
+
+ case EContactsActiveCompact:
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+ test.Next(_L("Start Active Compact on database"));
+ db->StartActiveCompactL();
+#endif
+ break;
+
+ case EContactsActiveRecover:
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+ test.Next(_L("Start Active Recover on database"));
+ db->StartActiveRecoverL();
+#endif
+ break;
+
+ case EContactsIdleSorter:
+ test.Next(_L("Start Contacts Idle Sorter"));
+ db->StartIdleSorterL(aStatus);
+ asyncRequest = ETrue;
+ break;
+
+ case EContactsIniFileTest:
+ // demonstrate database is open, read from it
+ test.Next(_L("Read a contact from database"));
+ db->ReadContactL();
+ break;
+
+ case EOpenRemoteViewOneContactForEdit:
+ test.Next(_L("Open a contact from database & open contact Remote View"));
+ if(clClient == 1) //There are two clients for this DB, first opens a view, second edits a contact
+ {
+ db->OpenRemoteViewL();
+ }
+ else
+ {
+ db->OpenContactL(KOpenContactId1);
+ }
+ break;
+ case EMultipleOpenOneContactForEdit:
+ test.Next(_L("Multiple clients, one closes contact item one leaves open"));
+ if (isCloseForBackup) //ETrue
+ {
+ db->OpenContactL(KOpenContactId1);
+ }
+ else //EFalse
+ {
+ db->OpenContactL(KOpenContactId2);
+ }
+
+ break;
+
+ }
+ }
+
+ return asyncRequest;
+ }
+
+
+
+// Reconnect disconnected client after Backup/Restore
+void CBackupTestFramework::ReconnectBackupClientTestCaseL()
+ {
+ // check that databases can be re-opened and are still useable
+ const TInt numDatabases = iContactClientSession.Count();
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ if (!iContactClientSession[i]->IsOpen())
+ {
+ test.Printf(_L("reopen database client # %i after backup/restore\n\r"), i + 1);
+ iContactClientSession[i]->OpenDatabaseL();
+ }
+
+ // read from db
+ test.Next(_L("Read a contact through database client"));
+ iContactClientSession[i]->ReadContactL();
+ }
+ }
+
+
+// test action if client didn't close database
+void CBackupTestFramework::CheckConnectionAfterBackupForTestCaseL()
+ {
+ const TInt numDatabases = iContactClientSession.Count();
+
+ // specific test case behaviour
+ switch (iTestCase->iActivity)
+ {
+ // activities that do not block backup / restore
+ case EIdleClient:
+ case EOpenLocalView:
+ case EOpenRemoteView:
+ case EContactsIniFileTest:
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ // read from each db
+ test.Next(_L("Read a contact through database client"));
+ iContactClientSession[i]->ReadContactL();
+ }
+ break;
+
+ case ERestoreCorruptDbTest:
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ // read from each db
+ test.Next(_L("Read a contact through database client"));
+ TRAPD(err, iContactClientSession[i]->ReadContactL());
+
+ // The restore is complete. The corrupted db file was damaged
+ // but should have been recovered after the restore completed.
+ // However, the contact doesn't exist in the db. If the
+ // corrupted db file was totally unrecognizable then the recover
+ // wouldn't have been attempted and the db would be closed. This
+ // would then return KErrNotReady.
+ if((iTestStep == EPostRestore) &&
+ (iContactClientSession[i]->DatabaseName()==KBackupDatabaseFile1))
+ {
+ TEST_CONDITION(err==KErrNotFound);
+ }
+ else //others should not Leave, so propagate Leave if it occurs.
+ {
+ if(err != KErrNone)
+ {
+ User::Leave(err);
+ }
+ }
+ }
+#endif
+ break;
+
+ // activities that can block backup / restore
+ case EOpenOneContactForEdit:
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ test.Next(_L("Commit contact to database"));
+ iContactClientSession[i]->CommitContactL(KOpenContactId1);
+ }
+ break;
+
+ case EOpenTwoContactsForEdit:
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ test.Next(_L("Commit 2 contacts to database"));
+ iContactClientSession[i]->CommitContactL(KOpenContactId1);
+ iContactClientSession[i]->CommitContactL(KOpenContactId2);
+ }
+ break;
+
+ case EContactsAsyncFind:
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ test.Next(_L("Complete Async Find on database"));
+ iContactClientSession[i]->CompleteAsyncFindL();
+ }
+ break;
+
+ case EContactsActiveCompact:
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ test.Next(_L("Complete Active Compact on database"));
+ iContactClientSession[i]->CompleteActiveCompactL();
+ }
+ break;
+
+ case EContactsActiveRecover:
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ test.Next(_L("Complete Active Recover on database"));
+ iContactClientSession[i]->CompleteActiveRecoverL();
+ }
+ break;
+
+ case EContactsIdleSorter:
+ // nothing to do for this Use Case
+ break;
+ }
+ }
+
+
+
+// support methods for testing .Ini file Backup and Restore
+
+// any test case action required immediately before Backup start notifiction
+void CBackupTestFramework::PreBackupNotificationActionsL()
+ {
+ const TInt numDatabases = iContactClientSession.Count();
+
+ // specific test case behaviour
+ switch (iTestCase->iActivity)
+ {
+ case EIdleClient:
+ case ERestoreCorruptDbTest:
+ case EOpenLocalView:
+ case EOpenRemoteView:
+ case EOpenOneContactForEdit:
+ case EOpenTwoContactsForEdit:
+ case EContactsAsyncFind:
+ case EContactsActiveCompact:
+ case EContactsActiveRecover:
+ case EContactsIdleSorter:
+ // nothing to do for this Use Case
+ break;
+
+ case EContactsIniFileTest:
+ // make change to Contacts .ini file that should be Backed-up
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ // read from each db
+ test.Next(_L("Set Speed Dial 1 for database"));
+ iContactClientSession[i]->SetSpeedDialL(KSpeedDialContactId, KSpeedDialPositionOne);
+ }
+ break;
+ }
+ }
+
+
+// any test case action required after Backup completion
+void CBackupTestFramework::PostBackupActionsL()
+ {
+ const TInt numDatabases = iContactClientSession.Count();
+
+ // specific test case behaviour
+ switch (iTestCase->iActivity)
+ {
+ case EIdleClient:
+ case ERestoreCorruptDbTest:
+ case EOpenLocalView:
+ case EOpenRemoteView:
+ case EOpenOneContactForEdit:
+ case EOpenTwoContactsForEdit:
+ case EContactsAsyncFind:
+ case EContactsActiveCompact:
+ case EContactsActiveRecover:
+ case EContactsIdleSorter:
+ case EOpenRemoteViewOneContactForEdit:
+ case EMultipleOpenOneContactForEdit:
+
+ // nothing to do for this Use Case
+ break;
+
+ case EContactsIniFileTest:
+ // check Contacts .ini is correct
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ // read from each db
+ test.Next(_L("Check Speed Dial 1 still set for database"));
+ iContactClientSession[i]->CheckSpeedDialSetL(KSpeedDialContactId, KSpeedDialPositionOne);
+ }
+ break;
+ }
+ }
+
+
+// any test case action required immediately before Restore start notifiction
+void CBackupTestFramework::PreRestoreNotificationActionsL()
+ {
+ const TInt numDatabases = iContactClientSession.Count();
+
+ // specific test case behaviour
+ switch (iTestCase->iActivity)
+ {
+ case EIdleClient:
+ case ERestoreCorruptDbTest:
+ case EOpenLocalView:
+ case EOpenRemoteView:
+ case EOpenOneContactForEdit:
+ case EOpenTwoContactsForEdit:
+ case EContactsAsyncFind:
+ case EContactsActiveCompact:
+ case EContactsActiveRecover:
+ case EContactsIdleSorter:
+ case EOpenRemoteViewOneContactForEdit:
+ case EMultipleOpenOneContactForEdit:
+
+ // nothing to do for this Use Case
+ break;
+
+ case EContactsIniFileTest:
+ // make change to Contacts .ini file before Restore
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ // read from each db
+ test.Next(_L("Remove Speed Dial 1 from database"));
+ iContactClientSession[i]->RemoveSpeedDialL(KSpeedDialContactId, KSpeedDialPositionOne);
+ }
+ break;
+ }
+ }
+
+// any test case action required after Restore completion
+void CBackupTestFramework::PostRestoreActionsL()
+ {
+ const TInt numDatabases = iContactClientSession.Count();
+
+ // specific test case behaviour
+ switch (iTestCase->iActivity)
+ {
+ case EIdleClient:
+ case ERestoreCorruptDbTest:
+ case EOpenLocalView:
+ case EOpenRemoteView:
+ case EOpenOneContactForEdit:
+ case EOpenTwoContactsForEdit:
+ case EContactsAsyncFind:
+ case EContactsActiveCompact:
+ case EContactsActiveRecover:
+ case EContactsIdleSorter:
+ case EOpenRemoteViewOneContactForEdit:
+ case EMultipleOpenOneContactForEdit:
+
+ // nothing to do for this Use Case
+ break;
+
+ case EContactsIniFileTest:
+ // check Restored Contacts .ini file is the same as was Backed-up
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ // read from each db
+ test.Next(_L("Check Restored Speed Dial 1 from database"));
+ iContactClientSession[i]->CheckSpeedDialSetL(KSpeedDialContactId, KSpeedDialPositionOne);
+ }
+ break;
+ }
+ }
+
+
+
+
+// Backup and Restore test with chosen Use Case
+void CBackupTestFramework::BackupRestoreTestL()
+ {
+ // need to do type conversion in 2 steps
+ TPtrC title(iTestCase->iTestTitle);
+ test.Next(title);
+
+
+ // start backup & restore tests in Active Scheduler
+ iTestStep = EPreBackup;
+ After(0);
+ CActiveScheduler::Start();
+
+ // ensure databases closed & release resources
+ iContactClientSession.ResetAndDestroy();
+
+ // any error from active scheduler?
+ User::LeaveIfError(iTestError);
+ }
+
+
+
+void CBackupTestFramework::RunL()
+ {
+ TBool waitForAsyncRequest = EFalse;
+
+ if (iStatus.Int() != KErrCancel)
+ {
+ switch (iTestStep)
+ {
+ // Backup test
+ case EPreBackup:
+ test.Start(_L("Backup test"));
+
+ test.Start(_L("Prepare Backup test case, open database(s) etc..."));
+ waitForAsyncRequest = PrepareBackupClientTestCaseL(iStatus);
+
+ // reset count number of Backup notifications
+ iClientNotifications = 0;
+ iViewUnavailableCount = 0;
+ break;
+
+ case ENotifyBackupStart:
+ // any test case action required immediately before Backup start notifiction
+ PreBackupNotificationActionsL();
+
+ if(conn::EBackupIncrement == iTestCase->iBackupIncType)
+ {
+ test.Next(_L("notify start of incremental backup"));
+ iBackupHelper->StartBackupL(conn::EBURBackupPartial, conn::EBackupIncrement);
+ }
+ else
+ {
+ test.Next(_L("notify start of backup"));
+ iBackupHelper->StartBackupL(conn::EBURBackupFull, conn::EBackupBase);
+ }
+
+ break;
+
+ case ECheckBackupStartNotifications:
+ if(conn::EBackupIncrement == iTestCase->iBackupIncType)
+ {
+ test.Next(_L("check number of incremental backup start notifications"));
+ }
+ else
+ {
+ test.Next(_L("check number of backup start notifications"));
+ }
+ TEST_CONDITION(iContactClientSession.Count() == iClientNotifications);
+
+ // test case has views?
+ if ((iTestCase->iActivity == EOpenLocalView) || (iTestCase->iActivity == EOpenRemoteView))
+ {
+ if (iTestCase->iCloseForBackup)
+ {
+ // Contacts clients close for Backup or Restore
+ test.Next(_L("check not too many Contact View unavailable notifications"));
+ TEST_CONDITION((iTestCase->iNumDatabases * iTestCase->iClientsPerDatabase) >= iViewUnavailableCount);
+ }
+ else
+ {
+ // Contacts clients open for Backup or Restore
+ test.Next(_L("check the number of Contact View unavailable notifications"));
+ TEST_CONDITION((iTestCase->iNumDatabases * iTestCase->iClientsPerDatabase) == iViewUnavailableCount);
+ }
+ }
+ break;
+
+ case EDoBackup:
+ if(conn::EBackupIncrement == iTestCase->iBackupIncType)
+ {
+ test.Next(_L("attempt incremental backup of database(s)"));
+ }
+ else
+ {
+ test.Next(_L("attempt backup of database(s)"));
+ }
+
+ // Clients have not closed for Backup?
+ if (iTestCase->iCloseForBackup != EAllCloseForBackup)
+ {
+ const TInt numDatabases = iContactClientSession.Count();
+
+ // find open database sessions
+ test.Next(_L("Check that new Read and Open.(Write) operations cannot start"));
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ if (! iContactClientSession[i]->IsCloseForBackup())
+ {
+ test.Next(_L("check that database read is locked"));
+ TRAPD(error, iContactClientSession[i]->ReadContactL());
+ TEST_CONDITION(KErrLocked == error);
+
+ test.Next(_L("check that database write is locked"));
+ TRAP(error, iContactClientSession[i]->OpenContactL(KOpenContactId3));
+ TEST_CONDITION(KErrLocked == error);
+
+ test.Next(_L("check that phone number lookup (database read) is locked"));
+ TRAP(error, iContactClientSession[i]->FindPhoneNumberL());
+ TEST_CONDITION(KErrLocked == error);
+ }
+ }
+ }
+
+ if(iTestCase->iActivity == EContactsIniFileTest)
+ {
+ test.Next(_L("checking that backup of cntmodel.ini file succeeds"));
+ TEST_CONDITION(iBackupHelper->SimulateIniBackup());
+ }
+
+ if (iTestCase->iExpectedBackupSuccess)
+ {
+ test.Next(_L("checking that backup of databases succeeds"));
+ TEST_CONDITION(iBackupHelper->SimulateDbBackup());
+ }
+ else
+ {
+ test.Next(_L("checking that backup of databases fails"));
+ TEST_CONDITION(! iBackupHelper->SimulateDbBackup());
+ }
+
+ // reset count for end of backup notifications
+ iClientNotifications = 0;
+ iViewReadyCount = 0;
+ break;
+
+ case ENotifyBackupEnd:
+ test.Next(_L("notify end of backup"));
+ iBackupHelper->EndBackupL();
+ break;
+
+ case ECheckBackupEndNotifications:
+ // if database connections are kept open
+ if (iTestCase->iCloseForBackup == EAllOpenForBackup)
+ {
+ test.Next(_L("check number of backup end notifications"));
+ TEST_CONDITION(iContactClientSession.Count() == iClientNotifications);
+
+ // test case kept views open?
+ if ((iTestCase->iActivity == EOpenLocalView) || (iTestCase->iActivity == EOpenRemoteView))
+ {
+ test.Next(_L("check the number of Contact View ready notifications"));
+ TEST_CONDITION((iTestCase->iNumDatabases * iTestCase->iClientsPerDatabase) == iViewReadyCount);
+ }
+ }
+ break;
+
+ case EPostBackup:
+ test.Next(_L("post backup verify database(s) useable"));
+ if (iTestCase->iCloseForBackup != EAllOpenForBackup)
+ {
+ ReconnectBackupClientTestCaseL();
+ }
+ else
+ {
+ CheckConnectionAfterBackupForTestCaseL();
+ }
+
+ // any test case action required after Backup completion
+ PostBackupActionsL();
+ break;
+
+ case EFinishedBackup:
+ test.Next(_L("Cleanup all client resources for test case"));
+ // cleanup after backup test
+ iContactClientSession.ResetAndDestroy();
+ test.End();
+ break;
+
+ // Successful Restore test
+ case EPreRestore:
+ test.Next(_L("Restore test"));
+
+ test.Start(_L("pre-restore access database(s)"));
+ waitForAsyncRequest = PrepareBackupClientTestCaseL(iStatus);
+
+ // reset count of Restore notifications
+ iClientNotifications = 0;
+ iViewUnavailableCount = 0;
+ break;
+
+ case ENotifyRestoreStart:
+ // any test case action required immediately before Restore start notifiction
+ PreRestoreNotificationActionsL();
+
+ test.Next(_L("notify start of restore"));
+ iBackupHelper->StartRestoreL();
+ break;
+
+ case ECheckRestoreStartNotifications:
+ test.Next(_L("check number of restore start notifications"));
+ TEST_CONDITION(iContactClientSession.Count() == iClientNotifications);
+
+ // test case has views?
+ if ((iTestCase->iActivity == EOpenLocalView) || (iTestCase->iActivity == EOpenRemoteView))
+ {
+ if (iTestCase->iCloseForBackup == EAllOpenForBackup)
+ {
+ // Contacts clients open for Backup or Restore
+ test.Next(_L("check the number of Contact View unavailable notifications"));
+ TEST_CONDITION((iTestCase->iNumDatabases * iTestCase->iClientsPerDatabase) == iViewUnavailableCount);
+ }
+ else
+ {
+ // Contacts clients close for Backup or Restore
+ test.Next(_L("check not too many Contact View unavailable notifications"));
+ TEST_CONDITION((iTestCase->iNumDatabases * iTestCase->iClientsPerDatabase) >= iViewUnavailableCount);
+ }
+ }
+ break;
+
+ case EDoRestore:
+ test.Next(_L("attempt restore of database(s)"));
+
+ // Clients have not closed for Backup?
+ if (iTestCase->iCloseForBackup == EAllOpenForBackup)
+
+ {
+ const TInt numDatabases = iContactClientSession.Count();
+
+ // find all open database sessions
+ for (TInt i = 0; i < numDatabases; i++)
+ {
+ test.Next(_L("check that database read is Locked"));
+ TRAPD(error, iContactClientSession[i]->ReadContactL());
+ TEST_CONDITION(KErrLocked == error);
+
+ test.Next(_L("check that database write is locked"));
+ TRAP(error, iContactClientSession[i]->OpenContactL(KOpenContactId3));
+ TEST_CONDITION(KErrLocked == error);
+
+ test.Next(_L("check that phone number lookup (database read) is locked"));
+ TRAP(error, iContactClientSession[i]->FindPhoneNumberL());
+ TEST_CONDITION(KErrLocked == error);
+ }
+ }
+ if(iTestCase->iActivity == EContactsIniFileTest)
+ {
+ test.Next(_L("checking that restore of ini file succeeds"));
+ TEST_CONDITION(iBackupHelper->SimulateIniRestore());
+ }
+
+ if (iTestCase->iExpectedBackupSuccess)
+ {
+ if (iTestCase->iActivity == ERestoreCorruptDbTest)
+ {
+ test.Next(_L("checking that restore of databases fails on the corrupted one"));
+ TEST_CONDITION(iBackupHelper->SimulateDamagedDbRestore());
+ }
+ else
+ {
+ test.Next(_L("checking that restore of databases succeeds"));
+ TEST_CONDITION(iBackupHelper->SimulateDbRestore());
+ }
+ }
+ else
+ {
+ test.Next(_L("checking that restore of databases fails"));
+ TEST_CONDITION(! iBackupHelper->SimulateDbRestore());
+ }
+
+ // reset count for end of Restore notifications
+ iClientNotifications = 0;
+ iViewReadyCount = 0;
+ break;
+
+ case ENotifyRestoreEnd:
+ test.Next(_L("notify end of restore"));
+ iBackupHelper->EndRestoreL();
+ break;
+
+ case ECheckRestoreEndNotifications:
+ // if database connections are kept open
+ if (iTestCase->iCloseForBackup == EAllOpenForBackup)
+ {
+ test.Next(_L("check number of restore end notifications"));
+ TEST_CONDITION(iContactClientSession.Count() == iClientNotifications);
+
+ // test case kept views open?
+ if ((iTestCase->iActivity == EOpenLocalView) || (iTestCase->iActivity == EOpenRemoteView))
+ {
+ test.Next(_L("check the number of Contact View ready notifications"));
+ TEST_CONDITION((iTestCase->iNumDatabases * iTestCase->iClientsPerDatabase) == iViewReadyCount);
+ }
+ }
+ break;
+
+ case EPostRestore:
+ test.Next(_L("post-restore verify database(s) useable"));
+ if (iTestCase->iCloseForBackup)
+ {
+ ReconnectBackupClientTestCaseL();
+ }
+ else
+ {
+ CheckConnectionAfterBackupForTestCaseL();
+ }
+
+ // any test case action required after Restore completion
+ PostRestoreActionsL();
+ break;
+
+ case EFinishedRestore:
+ test.Next(_L("Cleanup all client resources for test case"));
+ // cleanup after backup test
+ iContactClientSession.ResetAndDestroy();
+ // end x.y.z restore test
+ test.End();
+ // end x.y test case
+ test.End();
+
+ // overwrite corrupted database, other tests don't use it
+ if(iTestCase->iActivity == ERestoreCorruptDbTest)
+ {
+ // Copy a non-corrupted db over the corrupted one for other tests to use.
+ iBackupHelper->SimulateDbRestore();
+ }
+
+ // All Done
+ CActiveScheduler::Stop();
+ return;
+ }
+
+
+ // no pause required between steps?
+ if (waitForAsyncRequest)
+ // waits for an asynchronous request to complete
+ {
+ SetActive();
+ }
+ else if ((iTestStep == EPreBackup) || (iTestStep == EPreRestore))
+ {
+ // start of Backp or Restore test cycle - allow contacts client to settle (e.g. contacts view to sort)
+ test.Printf(_L("Wait %d ms to allow contacts client to settle (e.g. contacts view to sort)\n"), KWaitForClientToSettle);
+ After(KWaitForClientToSettle);
+ }
+ else if ((iTestStep == EPostBackup) || (iTestStep == EPostRestore))
+ {
+ // end of Backup or Restore test cycle - allow all system components to settle
+ test.Printf(_L("Wait %d ms to allow all system components to settle\n"), KWaitForSystemToSettle);
+ After(KWaitForSystemToSettle);
+ }
+ else if ((iTestStep == ENotifyBackupStart) || (iTestStep == ENotifyBackupEnd) || (iTestStep == ENotifyRestoreStart) || (iTestStep == ENotifyRestoreEnd))
+ {
+ // allow notification to propagate
+ test.Printf(_L("Wait %d ms to allow notification to propagate\n"), KWaitForBackupNotification);
+ After(KWaitForBackupNotification);
+ }
+ else
+ {
+ // minimum wait required
+ After(1);
+ }
+
+ // next step
+ iTestStep = (TBackupRestoreSteps) (iTestStep + 1);
+ }
+ }
+
+
+TInt CBackupTestFramework::RunError(TInt aError)
+ {
+ // RunL is verbose and prints details of each step
+ // so just print error info
+ test.Printf(_L("Backup and Restore test error %d (at step %d)\n\r"), aError, iTestStep);
+
+ // and state info
+ const TInt clientCount = iContactClientSession.Count();
+ for (TInt j = 0; j < clientCount; j++)
+ {
+ test.Printf(_L("client %i, IsOpen = %i, name \"%S\"\n\r"),
+ j, iContactClientSession[j]->IsOpen(), &iContactClientSession[j]->DatabaseName());
+ }
+
+ // propagate error
+ iTestError = aError;
+
+ CActiveScheduler::Stop();
+ return KErrNone;
+ }
+
+
+//
+
+CContactsClient* CBackupTestFramework::NewDatabaseClientL(const TDesC& aDatabaseName, TBool aCloseForBackup)
+ {
+ test.Printf(_L("open database \"%S\"\n\r"), &aDatabaseName);
+
+ // open a Contacts Model client for test case
+ CContactsClient* newClient = CContactsClient::NewLC(aDatabaseName, this, *this, aCloseForBackup);
+ CleanupStack::Check(newClient);
+
+ // remember for later cleanup
+ iContactClientSession.AppendL(newClient);
+ CleanupStack::Pop(newClient);
+ return newClient;
+ }
+
+
+void CBackupTestFramework::ContactsBackupRestoreObserver(CContactsClient& aContactClient, const TBool aRestore, const TBool aStart)
+ {
+ iClientNotifications ++;
+
+ // test case should respond to Backup / Restore notification ?
+ if (aStart && aContactClient.IsCloseForBackup())
+ {
+ test.Next(aRestore ? _L("Restore start notification - closing client") : _L("Backup start notification - closing client"));
+ aContactClient.CloseViews();
+ aContactClient.StartActiveClose();
+ }
+ }
+
+
+
+/*
+ Contact Views become EUnavailable when Backup or Restore start,
+ if the View is kept open it becomes EReady again afterwards.
+ */
+void CBackupTestFramework::HandleContactViewEvent(const CContactViewBase& /*aView*/,const TContactViewEvent& aEvent)
+ {
+ if (aEvent.iEventType == TContactViewEvent::EUnavailable)
+ {
+ iViewUnavailableCount++;
+ // reset Ready count for end of Backup or Restore
+ iViewReadyCount = 0;
+ }
+ else if (aEvent.iEventType == TContactViewEvent::EReady)
+ {
+ iViewReadyCount++;
+ }
+ }
+
+
+
+
+//
+
+
+LOCAL_C void TestCondition(TBool aCondition, TInt aLineNumber)
+ {
+ // if the test is about to fail, cleanup files first
+ if (!aCondition)
+ {
+ CBackupTestConductor::DeleteDatabases();
+ }
+ test.operator()(aCondition, aLineNumber);
+ }
+
+
+LOCAL_C void DoMainL(CActiveScheduler* scheduler)
+ {
+ CActiveScheduler::Install(scheduler);
+
+ CBackupTestConductor* tester = CBackupTestConductor::NewL();
+ CleanupStack::PushL(tester);
+
+ tester->RunTestsL();
+ CleanupStack::PopAndDestroy(tester);
+ }
+/**
+
+@SYMTestCaseID PIM-T-CNT-BACKUP-0001
+
+*/
+
+GLDEF_C TInt E32Main()
+ {
+ __UHEAP_MARK;
+ test.Title();
+ test.Start(_L("SYMTestCaseID:PIM-T-CNT-BACKUP-0001 Contacts Backup and Restore"));
+ CActiveScheduler* scheduler = new CActiveScheduler;
+ test(scheduler != NULL);
+ CTrapCleanup* theCleanup = CTrapCleanup::New();
+ User::LeaveIfError(TheFsSession.Connect());
+
+ test.Printf(_L("SECURE_DATA mode\r\n"));
+ User::After(KWaitForSystemToSettle);
+
+ TRAPD(ret,DoMainL(scheduler));
+ if (ret != KErrNone)
+ {
+ test.Printf(_L("Something in the test left with error code %d\n"), ret);
+ }
+ TEST_CONDITION(ret == KErrNone);
+
+ TheFsSession.Close();
+ delete theCleanup;
+ delete scheduler;
+ test.End();
+ test.Close();
+ __UHEAP_MARKEND;
+ return(KErrNone);
+ }