diff -r 000000000000 -r e686773b3f54 pimprotocols/phonebooksync/Test/TE_cntsync/te_cntsyncview.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimprotocols/phonebooksync/Test/TE_cntsync/te_cntsyncview.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,551 @@ +// Copyright (c) 2003-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: +// Tests that PhBkSync adds contacts from USIM address books to the contacts database, +// and that they appear correctly in the Contacts Model local view. +// +// + +#include +#include "te_cntsyncbase.h" +#include "te_cntsyncview.h" +#include + +// Values for User::After() +const TInt K1SecondWait(1000000); +const TInt K5SecondWait(5*K1SecondWait); +const TInt K20SecondWait(20*K1SecondWait); + +// Test config numbers... +const TInt KNormalSIMTestConfig(0); +const TInt KLockedSIMTestConfig(8); + +// Number of contacts on SIM cards +const TInt KNumContactsNormalSIM(5); +const TInt KNumContactsLockedSIM(25); + +class TViewCleanup + { + public: + TViewCleanup(CContactLocalView* aLocalView, CContactViewEventWait* aViewWaitEvent) + { + iLocalView = aLocalView; + iViewWaitEvent = aViewWaitEvent; + } + CContactViewEventWait* iViewWaitEvent; + CContactLocalView* iLocalView; + }; + +static void ViewCleanup(TAny* aPointer) + { + TViewCleanup* cleanup = static_cast (aPointer); + CContactLocalView* iLocalView = cleanup->iLocalView; + CContactViewEventWait* iViewWaitEvent = cleanup->iViewWaitEvent; + iLocalView->Close(*iViewWaitEvent); + delete iViewWaitEvent; + } + +/** + * Factory construction method. + * @return Pointer to CPhbkViewICCSyncTest object + */ +CPhbkViewICCSyncTest* CPhbkViewICCSyncTest::NewL() + { + CPhbkViewICCSyncTest* self = new(ELeave) CPhbkViewICCSyncTest(); + return self; + } + +/** + * Default constructor. Each test step initialises it's own name. + */ +CPhbkViewICCSyncTest::CPhbkViewICCSyncTest() + { + SetTestStepName(_L("ViewICCSyncTest")); + } + +/** + * Synchronisation of normal, unlocked, ICC. Creates a Contacts View + * with ICC entries only. + */ +enum TVerdict CPhbkViewICCSyncTest::doTestStepL() + { + SetSimTsyTestNumberL(0); + DoSyncL(); + + // all View tests use Manual Sync mode + User::LeaveIfError(iSession.SetSyncMode(RPhoneBookSession::EManual)); // Set mode to manual to avoid getting KErrInUse + CheckSyncModeL(RPhoneBookSession::EManual); + + // ICC unlocked + SetSimTsyTestNumberL(KNormalSIMTestConfig); + CleanupClosePushL(iViewSortOrder); + + // A sort order (only Family Name is present in ADN phonebooks) + iViewSortOrder.AppendL(KUidContactFieldFamilyName); + iViewSortOrder.AppendL(KUidContactFieldGivenName); + iViewSortOrder.AppendL(KUidContactFieldCompanyName); + + // Helper class that gives timed wait for View events + CContactViewEventWait *viewEventWait = CContactViewEventWait::NewL(); + CleanupStack::PushL(viewEventWait); + + // View with just ICC entries + iIccView = CContactLocalView::NewL(*viewEventWait, *iDb, iViewSortOrder, EICCEntriesOnly); + + CleanupStack::Pop();//viewEventWait will be deleted with cleanup below + TViewCleanup cleanup(iIccView, viewEventWait); + CleanupStack::PushL(TCleanupItem(ViewCleanup, &cleanup)); + + INFO_PRINTF1(_L(" Manual Sync")); + // do manual synchronisation + DoSyncL(); + WaitForSyncToCompleteL(); + + // let view catch up, waits 2s + INFO_PRINTF1(_L(" Wait for ICC view to become ready")); + // Wait 30s for View Event: EReady or ESortOrderChanged only + TBool eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse); + // check that event was received + TESTCHECKCONDITIONL(eventReceived); + TESTCHECKL(iEvent.iEventType, TContactViewEvent::EReady); + + INFO_PRINTF1(_L(" Check all PhoneBook entries are in view")); + TInt count = iIccView->CountL(); + if (count != KNumContactsNormalSIM) + { + INFO_PRINTF3(_L(" Expecting %d entries in View but found %d:"), + KNumContactsNormalSIM, count); + DumpICCViewL(); + } + TESTCHECK(count, KNumContactsNormalSIM); + + User::After(K5SecondWait); + CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder + + return TestStepResult(); + } + + +/** + * Factory construction method. + * @return Pointer to CPhbkViewICCLockedICCTest object + */ +CPhbkViewICCLockedICCTest* CPhbkViewICCLockedICCTest::NewL() + { + CPhbkViewICCLockedICCTest* self = new(ELeave) CPhbkViewICCLockedICCTest(); + return self; + } + +/** + * Default constructor. Each test step initialises it's own name. + */ +CPhbkViewICCLockedICCTest::CPhbkViewICCLockedICCTest() + { + SetTestStepName(_L("ViewICCLockedICCTest")); + } + +/** + * Synchronisation when ICC is locked. Creates a Contacts View of ICC entries + * only. + * + * Synchroniser is initially unable to perform synchronisation because ICC is locked. The + * Local View class recognises that the ICC is locked, and creates an empty View. + * + * When ICC becomes unlocked the synchronisation completes successfully. The Contacts Local + * View sees this, and re-sorts itself making the ICC entries appear in the View. + */ +enum TVerdict CPhbkViewICCLockedICCTest::doTestStepL() + { + // ICC locked, so initial Synchronisation is not carried out + SetSimTsyTestNumberL(KLockedSIMTestConfig); + CleanupClosePushL(iViewSortOrder); + // A sort order (only Family Name is present in ADN phonebooks) + iViewSortOrder.AppendL(KUidContactFieldFamilyName); + iViewSortOrder.AppendL(KUidContactFieldGivenName); + iViewSortOrder.AppendL(KUidContactFieldCompanyName); + + // Helper class that gives timed wait for View events + CContactViewEventWait *viewEventWait = CContactViewEventWait::NewL(); + CleanupStack::PushL(viewEventWait); + + // View with just ICC entries + iIccView = CContactLocalView::NewL(*viewEventWait, *iDb, iViewSortOrder, EICCEntriesOnly); + CleanupStack::Pop();//viewEventWait will be deleted with cleanup below + TViewCleanup cleanup(iIccView, viewEventWait); + CleanupStack::PushL(TCleanupItem(ViewCleanup, &cleanup)); + + INFO_PRINTF1(_L(" Initial Sync Failure")); + // check that ICC is locked + TRAPD(err, DoSyncFailL()); + if(err == KErrGeneral) + { + INFO_PRINTF1(_L("The view has already been created before we attempt to sync, so sync won't fail. We should finsh test here")); + SetTestStepResult(EPass); + CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder + return TestStepResult(); + } + TESTCHECKL(err, KErrNone); + User::After(K1SecondWait); + + RPhoneBookSession::TSyncState state; + iSession.GetPhoneBookCacheState(state); + + TESTCHECKL(state, RPhoneBookSession::EErrorDuringSync); // Cache not in valid state + + iSession.GetLastSyncError(err); + TESTCHECKL(err, KErrAccessDenied); // ICC locked + + // initially ready with no entries as ICC (SIM) card is not ready, waits 2s + INFO_PRINTF1(_L(" Check View becomes ready with no entries")); + // Wait 30seconds at max for View Event: EReady or ESortOrderChanged only + TBool eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse); + // check that event was received + TESTCHECKCONDITIONL(eventReceived); + + TESTCHECKL(iEvent.iEventType, TContactViewEvent::EReady); + TESTCHECKL(iIccView->CountL(), 0); // view should be empty + + // wait for ICC to become unlocked + INFO_PRINTF1(_L(" Start Sync when ICC becomes unlocked")); + User::After(K20SecondWait); // ICC should become unlocked now + DoSyncL(); + WaitForSyncToCompleteL(); + + // let the view catch up, waits 2s + INFO_PRINTF1(_L(" Wait for View to Re-Sort with ICC entries")); + // Wait 30seconds at max for View Event: EReady or ESortOrderChanged only + eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse); + // check that event was received + TESTCHECKCONDITIONL(eventReceived); + + INFO_PRINTF1(_L(" Contacts View should be resorted")); + TESTCHECKL(iEvent.iEventType, TContactViewEvent::ESortOrderChanged); + + INFO_PRINTF1(_L(" Check all PhoneBook entries are in view")); + TInt count = iIccView->CountL(); + if (count != KNumContactsLockedSIM) + { + INFO_PRINTF3(_L(" Expecting %d entries in View but found %d:"), + KNumContactsLockedSIM, count); + DumpICCViewL(); + } + TESTCHECK(count, KNumContactsLockedSIM); + + User::After(K5SecondWait); + CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder + + return TestStepResult(); + } + + +/** + * Factory construction method. + * @return Pointer to CPhbkViewICCLockedMixedTest object + */ +CPhbkViewICCLockedMixedTest* CPhbkViewICCLockedMixedTest::NewL() + { + CPhbkViewICCLockedMixedTest* self = new(ELeave) CPhbkViewICCLockedMixedTest(); + return self; + } + +/** + * Default constructor. Each test step initialises it's own name. + */ +CPhbkViewICCLockedMixedTest::CPhbkViewICCLockedMixedTest() + { + SetTestStepName(_L("ViewICCLockedMixedTest")); + } + +/** + * Synchronisation when ICC is locked. Creates a Contacts View of Contacts + * and ICC entries. This is similar to the ICC entries only test, but timing + * and behaviour of Contacts model is different. + * + * Synchroniser is initially unable to perform synchronisation because ICC is locked. The + * Local View class recognises that the ICC is locked, and creates a View without ICC entries. + * + * When ICC becomes unlocked the synchronisation completes successfully. The Contacts Local + * View sees this, and re-sorts itself making the ICC entries appear in the View. + */ +enum TVerdict CPhbkViewICCLockedMixedTest::doTestStepL() + { + // ICC locked, so initial Synchronisation is not carried out + SetSimTsyTestNumberL(KLockedSIMTestConfig); + CleanupClosePushL(iViewSortOrder); + + // A sort order (only Family Name is present in ADN phonebooks) + iViewSortOrder.AppendL(KUidContactFieldFamilyName); + iViewSortOrder.AppendL(KUidContactFieldGivenName); + iViewSortOrder.AppendL(KUidContactFieldCompanyName); + + // Helper class that gives timed wait for View events + CContactViewEventWait *viewEventWait = CContactViewEventWait::NewL(); + CleanupStack::PushL(viewEventWait); + + // View with ICC entries and contacts + iIccView = CContactLocalView::NewL(*viewEventWait, *iDb, iViewSortOrder, EICCEntriesAndContacts); + + CleanupStack::Pop();//viewEventWait will be deleted with cleanup below + TViewCleanup cleanup(iIccView, viewEventWait); + CleanupStack::PushL(TCleanupItem(ViewCleanup, &cleanup)); + + INFO_PRINTF1(_L(" Initial Sync Failure")); + // check that ICC is locked + TRAPD(err, DoSyncFailL()); + if(err == KErrGeneral) + { + INFO_PRINTF1(_L("The view has already been created before we attempt to sync, so sync won't fail. We should finsh test here")); + SetTestStepResult(EPass); + CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder + return TestStepResult(); + } + TESTCHECKL(err, KErrNone); + User::After(K1SecondWait); + + RPhoneBookSession::TSyncState state; + iSession.GetPhoneBookCacheState(state); + + TESTCHECKL(state, RPhoneBookSession::EErrorDuringSync); // Cache not in valid state + + iSession.GetLastSyncError(err); + TESTCHECKL(err, KErrAccessDenied); // ICC locked + + // initially ready with no entries as ICC (SIM) card is not ready, waits 2s + INFO_PRINTF1(_L(" Check View becomes ready without ICC entries")); + // Wait 30seconds at max for View Event: EReady or ESortOrderChanged only + TBool eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse); + // check that event was received + TESTCHECKCONDITIONL(eventReceived); + + TESTCHECKL(iEvent.iEventType, TContactViewEvent::EReady); + TESTCHECKL(iIccView->CountL(), 0); // view should be empty + + // wait for ICC to become unlocked + INFO_PRINTF1(_L(" Start Sync when ICC becomes unlocked")); + User::After(K20SecondWait); // ICC should become unlocked now + DoSyncL(); + WaitForSyncToCompleteL(); + + // let the view catch up, waits 2s + INFO_PRINTF1(_L(" Wait for View to Re-Sort with ICC entries")); + // Wait 30seconds at max for View Event: EReady or ESortOrderChanged only + eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse); + // check that event was received + TESTCHECKCONDITIONL(eventReceived); + + INFO_PRINTF1(_L(" Contacts View should be resorted")); + TESTCHECKL(iEvent.iEventType, TContactViewEvent::ESortOrderChanged); + + INFO_PRINTF1(_L(" Check all PhoneBook entries are in view")); + TInt count = iIccView->CountL(); + if (count != KNumContactsLockedSIM) + { + INFO_PRINTF3(_L(" Expecting %d entries in View but found %d:"), + KNumContactsLockedSIM, count); + DumpICCViewL(); + } + TESTCHECK(count, KNumContactsLockedSIM); + + User::After(K5SecondWait); + CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder + return TestStepResult(); + } + + +/** + * Synchronisation and create a view when just one phonebook exists. Previously + * a defect existed which would fail if no FDN phonebook was defined. + */ +enum TVerdict CPhbkViewICCSinglePhonebookTest::doTestStepL() + { + SetSimTsyTestNumberL(30); + + // + // Setup a sort order (only Family Name is present in ADN phonebooks) + // + INFO_PRINTF1(_L("Setup a sort order (only Family Name is present in ADN phonebooks)")); + CleanupClosePushL(iViewSortOrder); + iViewSortOrder.AppendL(KUidContactFieldFamilyName); + iViewSortOrder.AppendL(KUidContactFieldGivenName); + iViewSortOrder.AppendL(KUidContactFieldCompanyName); + + // + // Helper class that gives timed wait for View events + // + CContactViewEventWait *viewEventWait = CContactViewEventWait::NewL(); + CleanupStack::PushL(viewEventWait); + + // + // Create a view with ICC entries and contacts + // + INFO_PRINTF1(_L("Create a view with ICC entries and contacts")); + iIccView = CContactLocalView::NewL(*viewEventWait, *iDb, iViewSortOrder, EICCEntriesAndContacts); + + CleanupStack::Pop();//viewEventWait will be deleted with cleanup below + TViewCleanup cleanup(iIccView, viewEventWait); + CleanupStack::PushL(TCleanupItem(ViewCleanup, &cleanup)); + + // + // Sync ADN phonebook... + // + INFO_PRINTF1(_L(" Sync ADN phonebook...")); + TRequestStatus status; + + iSession.DoSynchronisation(status, KUidIccGlobalAdnPhonebook); + User::WaitForRequest(status); + TESTCHECKL(status.Int(), KErrNone); + + // + // Close view and clean up... + // + INFO_PRINTF1(_L(" Close view and clean up...")); + CleanupStack::PopAndDestroy(2); + + return TestStepResult(); + } // CPhbkViewICCSinglePhonebookTest::doTestStepL + + +void CPhbkSyncViewIntegrationTestBase::DumpICCViewL() + { + const TInt count = iIccView->CountL(); + + if (count == 0) + { + INFO_PRINTF1(_L(" No contacts to list.")); + return; + } + + CContactItem* contact = NULL; + TInt index; + + for (index = 0; index < count; index++) + { + const CViewContact& viewContact = iIccView->ContactAtL(index); + const TInt id = viewContact.Id(); + + // get actual Contact from DB + contact = iDb->ReadMinimalContactLC(id); + + // Get & print Contact's phone number + CContactItemFieldSet& fieldset = contact->CardFields(); + // look for Phone Number field in record + const TInt pos = fieldset.Find(KUidContactFieldPhoneNumber); + User::LeaveIfError(pos); // field must be present + CContactItemField& field = fieldset[pos]; + CContactTextField* textfield = field.TextStorage(); + + TBuf<128> outputString; + outputString.AppendFormat(_L(" [%04i] Id=%04i Name=\""), index+1, id); + outputString.Append(viewContact.Field(0)); + outputString.AppendFormat(_L("\" Number=\"")); + outputString.Append(textfield->Text()); + outputString.AppendFormat(_L("\"")); + INFO_PRINTF1(outputString); + + CleanupStack::PopAndDestroy(contact); + contact = NULL; + } + } + +// support class implementation, timed wait for View Event; (based on CContactViewEventQueue) + +CContactViewEventWait* CContactViewEventWait::NewL() + { + CContactViewEventWait* self = new(ELeave) CContactViewEventWait; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + +CContactViewEventWait::~CContactViewEventWait() + { + CTimer::Cancel(); + if (iView) iView->Close(*this); + } + + +/** + * Waits for an event from the database. + * + * @param aView Contact view to listen for events. + * @param aTimeOut Max time to wait for an event. + * @param aEvent The received event, undefined if this function returns false. + * @param aWaitForAny ETrue if wait is for any event, EFalse for view ready events only + * + * @return true if an event was received, false if timeout expired first. + */ +TBool CContactViewEventWait::WaitForViewEvent(CContactViewBase* aView, + TTimeIntervalSeconds aTimeOut, + TContactViewEvent& aEvent, + TBool aWaitForAny) + { + iView = aView; + iWaitForAny = aWaitForAny; + iTimedOut = EFalse; + CTimer::After(aTimeOut.Int() * 1000000); + + // wait for timer to finish or desired View event + CActiveScheduler::Start(); + + if (!iTimedOut) + { + aEvent = iEvent; + return ETrue; + } + else + { + return EFalse; + } + } + + +void CContactViewEventWait::RunL() + { + // Timer expired + iTimedOut = ETrue; + CActiveScheduler::Stop(); + } + + +void CContactViewEventWait::HandleContactViewEvent(const CContactViewBase& aView, + const TContactViewEvent& aEvent) + { + __ASSERT_ALWAYS(iView == &aView, User::Invariant()); + + // either waiting for Any event, or Ready or Ready after Re-sort + if(iWaitForAny || aEvent.iEventType == TContactViewEvent::EReady || + aEvent.iEventType == TContactViewEvent::ESortOrderChanged) + { + iEvent = aEvent; + + CTimer::Cancel(); + CActiveScheduler::Stop(); + } + } + + +CContactViewEventWait::CContactViewEventWait() + : CTimer(CActive::EPriorityStandard) + { + } + + +void CContactViewEventWait::ConstructL() + { + CTimer::ConstructL(); + CActiveScheduler::Add(this); + iView = NULL; + } +